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/interp.h"
18 
19 #include <algorithm>
20 #include <cassert>
21 #include <cinttypes>
22 #include <cmath>
23 #include <limits>
24 #include <type_traits>
25 #include <vector>
26 
27 #include "src/interp/interp-internal.h"
28 
29 #include "src/cast.h"
30 #include "src/stream.h"
31 
32 namespace wabt {
33 namespace interp {
34 
35 // Differs from the normal CHECK_RESULT because this one is meant to return the
36 // interp Result type.
37 #undef CHECK_RESULT
38 #define CHECK_RESULT(expr)   \
39   do {                       \
40     if (WABT_FAILED(expr)) { \
41       return Result::Error;  \
42     }                        \
43   } while (0)
44 
45 // Differs from CHECK_RESULT since it can return different traps, not just
46 // Error. Also uses __VA_ARGS__ so templates can be passed without surrounding
47 // parentheses.
48 #define CHECK_TRAP(...)            \
49   do {                             \
50     Result result = (__VA_ARGS__); \
51     if (result != Result::Ok) {    \
52       return result;               \
53     }                              \
54   } while (0)
55 
TypedValueToString(const TypedValue & tv)56 std::string TypedValueToString(const TypedValue& tv) {
57   switch (tv.type) {
58     case Type::I32:
59       return StringPrintf("i32:%u", tv.get_i32());
60 
61     case Type::I64:
62       return StringPrintf("i64:%" PRIu64, tv.get_i64());
63 
64     case Type::F32: {
65       return StringPrintf("f32:%f", tv.get_f32());
66     }
67 
68     case Type::F64: {
69       return StringPrintf("f64:%f", tv.get_f64());
70     }
71 
72     case Type::V128:
73       return StringPrintf("v128 i32x4:0x%08x 0x%08x 0x%08x 0x%08x",
74                           tv.value.v128_bits.v[0], tv.value.v128_bits.v[1],
75                           tv.value.v128_bits.v[2], tv.value.v128_bits.v[3]);
76 
77     default:
78       WABT_UNREACHABLE;
79   }
80 }
81 
WriteTypedValue(Stream * stream,const TypedValue & tv)82 void WriteTypedValue(Stream* stream, const TypedValue& tv) {
83   std::string s = TypedValueToString(tv);
84   stream->WriteData(s.data(), s.size());
85 }
86 
WriteTypedValues(Stream * stream,const TypedValues & values)87 void WriteTypedValues(Stream* stream, const TypedValues& values) {
88   for (size_t i = 0; i < values.size(); ++i) {
89     WriteTypedValue(stream, values[i]);
90     if (i != values.size() - 1) {
91       stream->Writef(", ");
92     }
93   }
94 }
95 
96 #define V(name, str) str,
97 static const char* s_trap_strings[] = {FOREACH_INTERP_RESULT(V)};
98 #undef V
99 
ResultToString(Result result)100 const char* ResultToString(Result result) {
101   return s_trap_strings[static_cast<size_t>(result)];
102 }
103 
WriteResult(Stream * stream,const char * desc,Result result)104 void WriteResult(Stream* stream, const char* desc, Result result) {
105   stream->Writef("%s: %s\n", desc, ResultToString(result));
106 }
107 
WriteCall(Stream * stream,string_view module_name,string_view func_name,const TypedValues & args,const TypedValues & results,Result result)108 void WriteCall(Stream* stream,
109                string_view module_name,
110                string_view func_name,
111                const TypedValues& args,
112                const TypedValues& results,
113                Result result) {
114   if (!module_name.empty()) {
115     stream->Writef(PRIstringview ".", WABT_PRINTF_STRING_VIEW_ARG(module_name));
116   }
117   stream->Writef(PRIstringview "(", WABT_PRINTF_STRING_VIEW_ARG(func_name));
118   WriteTypedValues(stream, args);
119   stream->Writef(") =>");
120   if (result == Result::Ok) {
121     if (results.size() > 0) {
122       stream->Writef(" ");
123       WriteTypedValues(stream, results);
124     }
125     stream->Writef("\n");
126   } else {
127     WriteResult(stream, " error", result);
128   }
129 }
130 
Environment()131 Environment::Environment() : istream_(new OutputBuffer()) {}
132 
FindModuleIndex(string_view name) const133 Index Environment::FindModuleIndex(string_view name) const {
134   auto iter = module_bindings_.find(name.to_string());
135   if (iter == module_bindings_.end()) {
136     return kInvalidIndex;
137   }
138   return iter->second.index;
139 }
140 
FindModule(string_view name)141 Module* Environment::FindModule(string_view name) {
142   Index index = FindModuleIndex(name);
143   return index == kInvalidIndex ? nullptr : modules_[index].get();
144 }
145 
FindRegisteredModule(string_view name)146 Module* Environment::FindRegisteredModule(string_view name) {
147   bool retry = false;
148   while (true) {
149     auto iter = registered_module_bindings_.find(name.to_string());
150     if (iter != registered_module_bindings_.end()) {
151       return modules_[iter->second.index].get();
152     }
153 
154     if (retry) {
155       // If you return true from on_unknown_module, you must add the module
156       // using AppendHostModule().
157       assert(false);
158       break;
159     }
160 
161     if (on_unknown_module && on_unknown_module(this, name)) {
162       retry = true;
163       continue;
164     }
165     break;
166   }
167   return nullptr;
168 }
169 
Options(uint32_t value_stack_size,uint32_t call_stack_size)170 Thread::Options::Options(uint32_t value_stack_size, uint32_t call_stack_size)
171     : value_stack_size(value_stack_size), call_stack_size(call_stack_size) {}
172 
Thread(Environment * env,const Options & options)173 Thread::Thread(Environment* env, const Options& options)
174     : env_(env),
175       value_stack_(options.value_stack_size),
176       call_stack_(options.call_stack_size) {}
177 
FuncSignature(std::vector<Type> param_types,std::vector<Type> result_types)178 FuncSignature::FuncSignature(std::vector<Type> param_types,
179                              std::vector<Type> result_types)
180     : param_types(param_types), result_types(result_types) {}
181 
FuncSignature(Index param_count,Type * param_types,Index result_count,Type * result_types)182 FuncSignature::FuncSignature(Index param_count,
183                              Type* param_types,
184                              Index result_count,
185                              Type* result_types)
186     : param_types(param_types, param_types + param_count),
187       result_types(result_types, result_types + result_count) {}
188 
Module(bool is_host)189 Module::Module(bool is_host)
190     : memory_index(kInvalidIndex),
191       table_index(kInvalidIndex),
192       is_host(is_host) {}
193 
Module(string_view name,bool is_host)194 Module::Module(string_view name, bool is_host)
195     : name(name.to_string()),
196       memory_index(kInvalidIndex),
197       table_index(kInvalidIndex),
198       is_host(is_host) {}
199 
GetFuncExport(Environment * env,string_view name,Index sig_index)200 Export* Module::GetFuncExport(Environment* env,
201                               string_view name,
202                               Index sig_index) {
203   auto range = export_bindings.equal_range(name.to_string());
204   for (auto iter = range.first; iter != range.second; ++iter) {
205     const Binding& binding = iter->second;
206     Export* export_ = &exports[binding.index];
207     if (export_->kind == ExternalKind::Func) {
208       const Func* func = env->GetFunc(export_->index);
209       if (env->FuncSignaturesAreEqual(sig_index, func->sig_index)) {
210         return export_;
211       }
212     }
213   }
214 
215   // No match; check whether the module wants to spontaneously create a
216   // function of this name and signature.
217   Index index = OnUnknownFuncExport(name, sig_index);
218   if (index != kInvalidIndex) {
219     Export* export_ = &exports[index];
220     assert(export_->kind == ExternalKind::Func);
221     const Func* func = env->GetFunc(export_->index);
222     WABT_USE(func);
223     assert(env->FuncSignaturesAreEqual(sig_index, func->sig_index));
224     return export_;
225   }
226 
227   return nullptr;
228 }
229 
GetExport(string_view name)230 Export* Module::GetExport(string_view name) {
231   int field_index = export_bindings.FindIndex(name);
232   if (field_index < 0) {
233     return nullptr;
234   }
235   return &exports[field_index];
236 }
237 
AppendExport(ExternalKind kind,Index item_index,string_view name)238 Index Module::AppendExport(ExternalKind kind,
239                            Index item_index,
240                            string_view name) {
241   exports.emplace_back(name, kind, item_index);
242   Export* export_ = &exports.back();
243   export_bindings.emplace(export_->name, Binding(exports.size() - 1));
244   return exports.size() - 1;
245 }
246 
DefinedModule()247 DefinedModule::DefinedModule()
248     : Module(false),
249       start_func_index(kInvalidIndex),
250       istream_start(kInvalidIstreamOffset),
251       istream_end(kInvalidIstreamOffset) {}
252 
HostModule(Environment * env,string_view name)253 HostModule::HostModule(Environment* env, string_view name)
254     : Module(name, true), env_(env) {}
255 
OnUnknownFuncExport(string_view name,Index sig_index)256 Index HostModule::OnUnknownFuncExport(string_view name, Index sig_index) {
257   if (on_unknown_func_export) {
258     return on_unknown_func_export(env_, this, name, sig_index);
259   }
260   return kInvalidIndex;
261 }
262 
AppendFuncExport(string_view name,const FuncSignature & sig,HostFunc::Callback callback)263 std::pair<HostFunc*, Index> HostModule::AppendFuncExport(
264     string_view name,
265     const FuncSignature& sig,
266     HostFunc::Callback callback) {
267   // TODO(binji): dedupe signature?
268   env_->EmplaceBackFuncSignature(sig);
269   Index sig_index = env_->GetFuncSignatureCount() - 1;
270   return AppendFuncExport(name, sig_index, callback);
271 }
272 
AppendFuncExport(string_view name,Index sig_index,HostFunc::Callback callback)273 std::pair<HostFunc*, Index> HostModule::AppendFuncExport(
274     string_view name,
275     Index sig_index,
276     HostFunc::Callback callback) {
277   auto* host_func = new HostFunc(this->name, name, sig_index, callback);
278   env_->EmplaceBackFunc(host_func);
279   Index func_env_index = env_->GetFuncCount() - 1;
280   Index export_index = AppendExport(ExternalKind::Func, func_env_index, name);
281   return {host_func, export_index};
282 }
283 
AppendTableExport(string_view name,Type elem_type,const Limits & limits)284 std::pair<Table*, Index> HostModule::AppendTableExport(string_view name,
285                                                        Type elem_type,
286                                                        const Limits& limits) {
287   Table* table = env_->EmplaceBackTable(elem_type, limits);
288   Index table_env_index = env_->GetTableCount() - 1;
289   Index export_index = AppendExport(ExternalKind::Table, table_env_index, name);
290   return {table, export_index};
291 }
292 
AppendMemoryExport(string_view name,const Limits & limits)293 std::pair<Memory*, Index> HostModule::AppendMemoryExport(string_view name,
294                                                          const Limits& limits) {
295   Memory* memory = env_->EmplaceBackMemory(limits);
296   Index memory_env_index = env_->GetMemoryCount() - 1;
297   Index export_index =
298       AppendExport(ExternalKind::Memory, memory_env_index, name);
299   return {memory, export_index};
300 }
301 
AppendGlobalExport(string_view name,Type type,bool mutable_)302 std::pair<Global*, Index> HostModule::AppendGlobalExport(string_view name,
303                                                          Type type,
304                                                          bool mutable_) {
305   Global* global = env_->EmplaceBackGlobal(TypedValue(type), mutable_);
306   Index global_env_index = env_->GetGlobalCount() - 1;
307   Index export_index =
308       AppendExport(ExternalKind::Global, global_env_index, name);
309   return {global, export_index};
310 }
311 
AppendGlobalExport(string_view name,bool mutable_,uint32_t value)312 std::pair<Global*, Index> HostModule::AppendGlobalExport(string_view name,
313                                              bool mutable_,
314                                              uint32_t value) {
315   std::pair<Global*, Index> pair =
316       AppendGlobalExport(name, Type::I32, mutable_);
317   pair.first->typed_value.set_i32(value);
318   return pair;
319 }
320 
AppendGlobalExport(string_view name,bool mutable_,uint64_t value)321 std::pair<Global*, Index> HostModule::AppendGlobalExport(string_view name,
322                                              bool mutable_,
323                                              uint64_t value) {
324   std::pair<Global*, Index> pair =
325       AppendGlobalExport(name, Type::I64, mutable_);
326   pair.first->typed_value.set_i64(value);
327   return pair;
328 }
329 
AppendGlobalExport(string_view name,bool mutable_,float value)330 std::pair<Global*, Index> HostModule::AppendGlobalExport(string_view name,
331                                              bool mutable_,
332                                              float value) {
333   std::pair<Global*, Index> pair =
334       AppendGlobalExport(name, Type::F32, mutable_);
335   pair.first->typed_value.set_f32(value);
336   return pair;
337 }
338 
AppendGlobalExport(string_view name,bool mutable_,double value)339 std::pair<Global*, Index> HostModule::AppendGlobalExport(string_view name,
340                                              bool mutable_,
341                                              double value) {
342   std::pair<Global*, Index> pair =
343       AppendGlobalExport(name, Type::F64, mutable_);
344   pair.first->typed_value.set_f64(value);
345   return pair;
346 }
347 
Mark()348 Environment::MarkPoint Environment::Mark() {
349   MarkPoint mark;
350   mark.modules_size = modules_.size();
351   mark.sigs_size = sigs_.size();
352   mark.funcs_size = funcs_.size();
353   mark.memories_size = memories_.size();
354   mark.tables_size = tables_.size();
355   mark.globals_size = globals_.size();
356   mark.data_segments_size = data_segments_.size();
357   mark.elem_segments_size = elem_segments_.size();
358   mark.istream_size = istream_->data.size();
359   return mark;
360 }
361 
ResetToMarkPoint(const MarkPoint & mark)362 void Environment::ResetToMarkPoint(const MarkPoint& mark) {
363   // Destroy entries in the binding hash.
364   for (size_t i = mark.modules_size; i < modules_.size(); ++i) {
365     std::string name = modules_[i]->name;
366     if (!name.empty()) {
367       module_bindings_.erase(name);
368     }
369   }
370 
371   // registered_module_bindings_ maps from an arbitrary name to a module index,
372   // so we have to iterate through the entire table to find entries to remove.
373   auto iter = registered_module_bindings_.begin();
374   while (iter != registered_module_bindings_.end()) {
375     if (iter->second.index >= mark.modules_size) {
376       iter = registered_module_bindings_.erase(iter);
377     } else {
378       ++iter;
379     }
380   }
381 
382   modules_.erase(modules_.begin() + mark.modules_size, modules_.end());
383   sigs_.erase(sigs_.begin() + mark.sigs_size, sigs_.end());
384   funcs_.erase(funcs_.begin() + mark.funcs_size, funcs_.end());
385   memories_.erase(memories_.begin() + mark.memories_size, memories_.end());
386   tables_.erase(tables_.begin() + mark.tables_size, tables_.end());
387   globals_.erase(globals_.begin() + mark.globals_size, globals_.end());
388   data_segments_.erase(data_segments_.begin() + mark.data_segments_size,
389                        data_segments_.end());
390   elem_segments_.erase(elem_segments_.begin() + mark.elem_segments_size,
391                        elem_segments_.end());
392   istream_->data.resize(mark.istream_size);
393 }
394 
AppendHostModule(string_view name)395 HostModule* Environment::AppendHostModule(string_view name) {
396   HostModule* module = new HostModule(this, name);
397   modules_.emplace_back(module);
398   registered_module_bindings_.emplace(name.to_string(),
399                                       Binding(modules_.size() - 1));
400   return module;
401 }
402 
ToRep(bool x)403 uint32_t ToRep(bool x) { return x ? 1 : 0; }
ToRep(uint32_t x)404 uint32_t ToRep(uint32_t x) { return x; }
ToRep(uint64_t x)405 uint64_t ToRep(uint64_t x) { return x; }
ToRep(int32_t x)406 uint32_t ToRep(int32_t x) { return Bitcast<uint32_t>(x); }
ToRep(int64_t x)407 uint64_t ToRep(int64_t x) { return Bitcast<uint64_t>(x); }
ToRep(float x)408 uint32_t ToRep(float x) { return Bitcast<uint32_t>(x); }
ToRep(double x)409 uint64_t ToRep(double x) { return Bitcast<uint64_t>(x); }
ToRep(v128 x)410 v128     ToRep(v128 x) { return Bitcast<v128>(x); }
411 
412 template <typename Dst, typename Src>
413 Dst FromRep(Src x);
414 
415 template <>
FromRep(uint32_t x)416 uint32_t FromRep<uint32_t>(uint32_t x) { return x; }
417 template <>
FromRep(uint64_t x)418 uint64_t FromRep<uint64_t>(uint64_t x) { return x; }
419 template <>
FromRep(uint32_t x)420 int32_t FromRep<int32_t>(uint32_t x) { return Bitcast<int32_t>(x); }
421 template <>
FromRep(uint64_t x)422 int64_t FromRep<int64_t>(uint64_t x) { return Bitcast<int64_t>(x); }
423 template <>
FromRep(uint32_t x)424 float FromRep<float>(uint32_t x) { return Bitcast<float>(x); }
425 template <>
FromRep(uint64_t x)426 double FromRep<double>(uint64_t x) { return Bitcast<double>(x); }
427 template <>
FromRep(v128 x)428 v128 FromRep<v128>(v128 x) { return Bitcast<v128>(x); }
429 
430 template <typename T>
431 struct FloatTraits;
432 
433 template <typename R, typename T>
434 bool IsConversionInRange(ValueTypeRep<T> bits);
435 
436 /* 3 32222222 222...00
437  * 1 09876543 210...10
438  * -------------------
439  * 0 00000000 000...00 => 0x00000000 => 0
440  * 0 10011101 111...11 => 0x4effffff => 2147483520                  (~INT32_MAX)
441  * 0 10011110 000...00 => 0x4f000000 => 2147483648
442  * 0 10011110 111...11 => 0x4f7fffff => 4294967040                 (~UINT32_MAX)
443  * 0 10111110 111...11 => 0x5effffff => 9223371487098961920         (~INT64_MAX)
444  * 0 10111110 000...00 => 0x5f000000 => 9223372036854775808
445  * 0 10111111 111...11 => 0x5f7fffff => 18446742974197923840       (~UINT64_MAX)
446  * 0 10111111 000...00 => 0x5f800000 => 18446744073709551616
447  * 0 11111111 000...00 => 0x7f800000 => inf
448  * 0 11111111 000...01 => 0x7f800001 => nan(0x1)
449  * 0 11111111 111...11 => 0x7fffffff => nan(0x7fffff)
450  * 1 00000000 000...00 => 0x80000000 => -0
451  * 1 01111110 111...11 => 0xbf7fffff => -1 + ulp      (~UINT32_MIN, ~UINT64_MIN)
452  * 1 01111111 000...00 => 0xbf800000 => -1
453  * 1 10011110 000...00 => 0xcf000000 => -2147483648                  (INT32_MIN)
454  * 1 10111110 000...00 => 0xdf000000 => -9223372036854775808         (INT64_MIN)
455  * 1 11111111 000...00 => 0xff800000 => -inf
456  * 1 11111111 000...01 => 0xff800001 => -nan(0x1)
457  * 1 11111111 111...11 => 0xffffffff => -nan(0x7fffff)
458  */
459 
460 template <>
461 struct FloatTraits<float> {
462   static const uint32_t kMax = 0x7f7fffffU;
463   static const uint32_t kInf = 0x7f800000U;
464   static const uint32_t kNegMax = 0xff7fffffU;
465   static const uint32_t kNegInf = 0xff800000U;
466   static const uint32_t kNegOne = 0xbf800000U;
467   static const uint32_t kNegZero = 0x80000000U;
468   static const uint32_t kQuietNan = 0x7fc00000U;
469   static const uint32_t kQuietNegNan = 0xffc00000U;
470   static const int kSigBits = 23;
471   static const uint32_t kSigMask = 0x7fffff;
472   static const uint32_t kSignMask = 0x80000000U;
473 
IsNanwabt::interp::FloatTraits474   static bool IsNan(uint32_t bits) {
475     return (bits > kInf && bits < kNegZero) || (bits > kNegInf);
476   }
477 
IsZerowabt::interp::FloatTraits478   static bool IsZero(uint32_t bits) { return bits == 0 || bits == kNegZero; }
479 
IsCanonicalNanwabt::interp::FloatTraits480   static bool IsCanonicalNan(uint32_t bits) {
481     return bits == kQuietNan || bits == kQuietNegNan;
482   }
483 
IsArithmeticNanwabt::interp::FloatTraits484   static bool IsArithmeticNan(uint32_t bits) {
485     return (bits & kQuietNan) == kQuietNan;
486   }
487 
CanonicalizeNanwabt::interp::FloatTraits488   static uint32_t CanonicalizeNan(uint32_t bits) {
489     return WABT_UNLIKELY(IsNan(bits)) ? kQuietNan : bits;
490   }
491 };
492 
IsCanonicalNan(uint32_t bits)493 bool IsCanonicalNan(uint32_t bits) {
494   return FloatTraits<float>::IsCanonicalNan(bits);
495 }
496 
IsArithmeticNan(uint32_t bits)497 bool IsArithmeticNan(uint32_t bits) {
498   return FloatTraits<float>::IsArithmeticNan(bits);
499 }
500 
501 template <>
IsConversionInRange(uint32_t bits)502 bool IsConversionInRange<int32_t, float>(uint32_t bits) {
503   return (bits < 0x4f000000U) ||
504          (bits >= FloatTraits<float>::kNegZero && bits <= 0xcf000000U);
505 }
506 
507 template <>
IsConversionInRange(uint32_t bits)508 bool IsConversionInRange<int64_t, float>(uint32_t bits) {
509   return (bits < 0x5f000000U) ||
510          (bits >= FloatTraits<float>::kNegZero && bits <= 0xdf000000U);
511 }
512 
513 template <>
IsConversionInRange(uint32_t bits)514 bool IsConversionInRange<uint32_t, float>(uint32_t bits) {
515   return (bits < 0x4f800000U) || (bits >= FloatTraits<float>::kNegZero &&
516                                   bits < FloatTraits<float>::kNegOne);
517 }
518 
519 template <>
IsConversionInRange(uint32_t bits)520 bool IsConversionInRange<uint64_t, float>(uint32_t bits) {
521   return (bits < 0x5f800000U) || (bits >= FloatTraits<float>::kNegZero &&
522                                   bits < FloatTraits<float>::kNegOne);
523 }
524 
525 /*
526  * 6 66655555555 5544..2..222221...000
527  * 3 21098765432 1098..9..432109...210
528  * -----------------------------------
529  * 0 00000000000 0000..0..000000...000 0x0000000000000000 => 0
530  * 0 10000011101 1111..1..111000...000 0x41dfffffffc00000 => 2147483647           (INT32_MAX)
531  * 0 10000011110 1111..1..111100...000 0x41efffffffe00000 => 4294967295           (UINT32_MAX)
532  * 0 10000111101 1111..1..111111...111 0x43dfffffffffffff => 9223372036854774784  (~INT64_MAX)
533  * 0 10000111110 0000..0..000000...000 0x43e0000000000000 => 9223372036854775808
534  * 0 10000111110 1111..1..111111...111 0x43efffffffffffff => 18446744073709549568 (~UINT64_MAX)
535  * 0 10000111111 0000..0..000000...000 0x43f0000000000000 => 18446744073709551616
536  * 0 10001111110 1111..1..000000...000 0x47efffffe0000000 => 3.402823e+38         (FLT_MAX)
537  * 0 11111111111 0000..0..000000...000 0x7ff0000000000000 => inf
538  * 0 11111111111 0000..0..000000...001 0x7ff0000000000001 => nan(0x1)
539  * 0 11111111111 1111..1..111111...111 0x7fffffffffffffff => nan(0xfff...)
540  * 1 00000000000 0000..0..000000...000 0x8000000000000000 => -0
541  * 1 01111111110 1111..1..111111...111 0xbfefffffffffffff => -1 + ulp             (~UINT32_MIN, ~UINT64_MIN)
542  * 1 01111111111 0000..0..000000...000 0xbff0000000000000 => -1
543  * 1 10000011110 0000..0..000000...000 0xc1e0000000000000 => -2147483648          (INT32_MIN)
544  * 1 10000111110 0000..0..000000...000 0xc3e0000000000000 => -9223372036854775808 (INT64_MIN)
545  * 1 10001111110 1111..1..000000...000 0xc7efffffe0000000 => -3.402823e+38        (-FLT_MAX)
546  * 1 11111111111 0000..0..000000...000 0xfff0000000000000 => -inf
547  * 1 11111111111 0000..0..000000...001 0xfff0000000000001 => -nan(0x1)
548  * 1 11111111111 1111..1..111111...111 0xffffffffffffffff => -nan(0xfff...)
549  */
550 
551 template <>
552 struct FloatTraits<double> {
553   static const uint64_t kInf = 0x7ff0000000000000ULL;
554   static const uint64_t kNegInf = 0xfff0000000000000ULL;
555   static const uint64_t kNegOne = 0xbff0000000000000ULL;
556   static const uint64_t kNegZero = 0x8000000000000000ULL;
557   static const uint64_t kQuietNan = 0x7ff8000000000000ULL;
558   static const uint64_t kQuietNegNan = 0xfff8000000000000ULL;
559   static const int kSigBits = 52;
560   static const uint64_t kSigMask = 0xfffffffffffffULL;
561   static const uint64_t kSignMask = 0x8000000000000000ULL;
562 
IsNanwabt::interp::FloatTraits563   static bool IsNan(uint64_t bits) {
564     return (bits > kInf && bits < kNegZero) || (bits > kNegInf);
565   }
566 
IsZerowabt::interp::FloatTraits567   static bool IsZero(uint64_t bits) { return bits == 0 || bits == kNegZero; }
568 
IsCanonicalNanwabt::interp::FloatTraits569   static bool IsCanonicalNan(uint64_t bits) {
570     return bits == kQuietNan || bits == kQuietNegNan;
571   }
572 
IsArithmeticNanwabt::interp::FloatTraits573   static bool IsArithmeticNan(uint64_t bits) {
574     return (bits & kQuietNan) == kQuietNan;
575   }
576 
CanonicalizeNanwabt::interp::FloatTraits577   static uint64_t CanonicalizeNan(uint64_t bits) {
578     return WABT_UNLIKELY(IsNan(bits)) ? kQuietNan : bits;
579   }
580 };
581 
IsCanonicalNan(uint64_t bits)582 bool IsCanonicalNan(uint64_t bits) {
583   return FloatTraits<double>::IsCanonicalNan(bits);
584 }
585 
IsArithmeticNan(uint64_t bits)586 bool IsArithmeticNan(uint64_t bits) {
587   return FloatTraits<double>::IsArithmeticNan(bits);
588 }
589 
590 template <>
IsConversionInRange(uint64_t bits)591 bool IsConversionInRange<int32_t, double>(uint64_t bits) {
592   return (bits <= 0x41dfffffffc00000ULL) ||
593          (bits >= FloatTraits<double>::kNegZero &&
594           bits <= 0xc1e0000000000000ULL);
595 }
596 
597 template <>
IsConversionInRange(uint64_t bits)598 bool IsConversionInRange<int64_t, double>(uint64_t bits) {
599   return (bits < 0x43e0000000000000ULL) ||
600          (bits >= FloatTraits<double>::kNegZero &&
601           bits <= 0xc3e0000000000000ULL);
602 }
603 
604 template <>
IsConversionInRange(uint64_t bits)605 bool IsConversionInRange<uint32_t, double>(uint64_t bits) {
606   return (bits <= 0x41efffffffe00000ULL) ||
607          (bits >= FloatTraits<double>::kNegZero &&
608           bits < FloatTraits<double>::kNegOne);
609 }
610 
611 template <>
IsConversionInRange(uint64_t bits)612 bool IsConversionInRange<uint64_t, double>(uint64_t bits) {
613   return (bits < 0x43f0000000000000ULL) ||
614          (bits >= FloatTraits<double>::kNegZero &&
615           bits < FloatTraits<double>::kNegOne);
616 }
617 
618 template <>
IsConversionInRange(uint64_t bits)619 bool IsConversionInRange<float, double>(uint64_t bits) {
620   return (bits <= 0x47efffffe0000000ULL) ||
621          (bits >= FloatTraits<double>::kNegZero &&
622           bits <= 0xc7efffffe0000000ULL);
623 }
624 
625 // The WebAssembly rounding mode means that these values (which are > F32_MAX)
626 // should be rounded to F32_MAX and not set to infinity. Unfortunately, UBSAN
627 // complains that the value is not representable as a float, so we'll special
628 // case them.
IsInRangeF64DemoteF32RoundToF32Max(uint64_t bits)629 bool IsInRangeF64DemoteF32RoundToF32Max(uint64_t bits) {
630   return bits > 0x47efffffe0000000ULL && bits < 0x47effffff0000000ULL;
631 }
632 
IsInRangeF64DemoteF32RoundToNegF32Max(uint64_t bits)633 bool IsInRangeF64DemoteF32RoundToNegF32Max(uint64_t bits) {
634   return bits > 0xc7efffffe0000000ULL && bits < 0xc7effffff0000000ULL;
635 }
636 
637 template <typename T, typename MemType> struct ExtendMemType;
638 template<> struct ExtendMemType<uint32_t, uint8_t> { typedef uint32_t type; };
639 template<> struct ExtendMemType<uint32_t, int8_t> { typedef int32_t type; };
640 template<> struct ExtendMemType<uint32_t, uint16_t> { typedef uint32_t type; };
641 template<> struct ExtendMemType<uint32_t, int16_t> { typedef int32_t type; };
642 template<> struct ExtendMemType<uint32_t, uint32_t> { typedef uint32_t type; };
643 template<> struct ExtendMemType<uint32_t, int32_t> { typedef int32_t type; };
644 template<> struct ExtendMemType<uint64_t, uint8_t> { typedef uint64_t type; };
645 template<> struct ExtendMemType<uint64_t, int8_t> { typedef int64_t type; };
646 template<> struct ExtendMemType<uint64_t, uint16_t> { typedef uint64_t type; };
647 template<> struct ExtendMemType<uint64_t, int16_t> { typedef int64_t type; };
648 template<> struct ExtendMemType<uint64_t, uint32_t> { typedef uint64_t type; };
649 template<> struct ExtendMemType<uint64_t, int32_t> { typedef int64_t type; };
650 template<> struct ExtendMemType<uint64_t, uint64_t> { typedef uint64_t type; };
651 template<> struct ExtendMemType<uint64_t, int64_t> { typedef int64_t type; };
652 template<> struct ExtendMemType<float, float> { typedef float type; };
653 template<> struct ExtendMemType<double, double> { typedef double type; };
654 template<> struct ExtendMemType<v128, v128> { typedef v128 type; };
655 
656 template <typename T, typename MemType> struct WrapMemType;
657 template<> struct WrapMemType<uint32_t, uint8_t> { typedef uint8_t type; };
658 template<> struct WrapMemType<uint32_t, uint16_t> { typedef uint16_t type; };
659 template<> struct WrapMemType<uint32_t, uint32_t> { typedef uint32_t type; };
660 template<> struct WrapMemType<uint64_t, uint8_t> { typedef uint8_t type; };
661 template<> struct WrapMemType<uint64_t, uint16_t> { typedef uint16_t type; };
662 template<> struct WrapMemType<uint64_t, uint32_t> { typedef uint32_t type; };
663 template<> struct WrapMemType<uint64_t, uint64_t> { typedef uint64_t type; };
664 template<> struct WrapMemType<float, float> { typedef uint32_t type; };
665 template<> struct WrapMemType<double, double> { typedef uint64_t type; };
666 template<> struct WrapMemType<v128, v128> { typedef v128 type; };
667 
668 template <typename T>
669 Value MakeValue(ValueTypeRep<T>);
670 
671 template <>
MakeValue(uint32_t v)672 Value MakeValue<uint32_t>(uint32_t v) {
673   Value result;
674   result.i32 = v;
675   return result;
676 }
677 
678 template <>
MakeValue(uint32_t v)679 Value MakeValue<int32_t>(uint32_t v) {
680   Value result;
681   result.i32 = v;
682   return result;
683 }
684 
685 template <>
MakeValue(uint64_t v)686 Value MakeValue<uint64_t>(uint64_t v) {
687   Value result;
688   result.i64 = v;
689   return result;
690 }
691 
692 template <>
MakeValue(uint64_t v)693 Value MakeValue<int64_t>(uint64_t v) {
694   Value result;
695   result.i64 = v;
696   return result;
697 }
698 
699 template <>
MakeValue(uint32_t v)700 Value MakeValue<float>(uint32_t v) {
701   Value result;
702   result.f32_bits = v;
703   return result;
704 }
705 
706 template <>
MakeValue(uint64_t v)707 Value MakeValue<double>(uint64_t v) {
708   Value result;
709   result.f64_bits = v;
710   return result;
711 }
712 
713 template <>
MakeValue(v128 v)714 Value MakeValue<v128>(v128 v) {
715   Value result;
716   result.v128_bits = v;
717   return result;
718 }
719 
720 template <typename T> ValueTypeRep<T> GetValue(Value);
GetValue(Value v)721 template<> uint32_t GetValue<int32_t>(Value v) { return v.i32; }
GetValue(Value v)722 template<> uint32_t GetValue<uint32_t>(Value v) { return v.i32; }
GetValue(Value v)723 template<> uint64_t GetValue<int64_t>(Value v) { return v.i64; }
GetValue(Value v)724 template<> uint64_t GetValue<uint64_t>(Value v) { return v.i64; }
GetValue(Value v)725 template<> uint32_t GetValue<float>(Value v) { return v.f32_bits; }
GetValue(Value v)726 template<> uint64_t GetValue<double>(Value v) { return v.f64_bits; }
GetValue(Value v)727 template<> v128 GetValue<v128>(Value v) { return v.v128_bits; }
728 
729 template <typename T>
CanonicalizeNan(ValueTypeRep<T> rep)730 ValueTypeRep<T> CanonicalizeNan(ValueTypeRep<T> rep) {
731   return rep;
732 }
733 
734 template <>
CanonicalizeNan(ValueTypeRep<float> rep)735 ValueTypeRep<float> CanonicalizeNan<float>(ValueTypeRep<float> rep) {
736   return FloatTraits<float>::CanonicalizeNan(rep);
737 }
738 
739 template <>
CanonicalizeNan(ValueTypeRep<double> rep)740 ValueTypeRep<double> CanonicalizeNan<double>(ValueTypeRep<double> rep) {
741   return FloatTraits<double>::CanonicalizeNan(rep);
742 }
743 
744 #define TRAP(type) return Result::Trap##type
745 #define TRAP_UNLESS(cond, type) TRAP_IF(!(cond), type)
746 #define TRAP_IF(cond, type)    \
747   do {                         \
748     if (WABT_UNLIKELY(cond)) { \
749       TRAP(type);              \
750     }                          \
751   } while (0)
752 
753 #define CHECK_STACK() \
754   TRAP_IF(value_stack_top_ >= value_stack_.size(), ValueStackExhausted)
755 
756 #define PUSH_NEG_1_AND_BREAK_IF(cond) \
757   if (WABT_UNLIKELY(cond)) {          \
758     CHECK_TRAP(Push<int32_t>(-1));    \
759     break;                            \
760   }
761 
762 #define GOTO(offset) pc = &istream[offset]
763 
ReadMemory(const uint8_t ** pc)764 Memory* Thread::ReadMemory(const uint8_t** pc) {
765   Index memory_index = ReadU32(pc);
766   return &env_->memories_[memory_index];
767 }
768 
ReadTable(const uint8_t ** pc)769 Table* Thread::ReadTable(const uint8_t** pc) {
770   Index table_index = ReadU32(pc);
771   return &env_->tables_[table_index];
772 }
773 
774 template <typename MemType>
GetAccessAddress(const uint8_t ** pc,void ** out_address)775 Result Thread::GetAccessAddress(const uint8_t** pc, void** out_address) {
776   Memory* memory = ReadMemory(pc);
777   uint64_t addr = static_cast<uint64_t>(Pop<uint32_t>()) + ReadU32(pc);
778   TRAP_IF(addr + sizeof(MemType) > memory->data.size(),
779           MemoryAccessOutOfBounds);
780   *out_address = memory->data.data() + static_cast<IstreamOffset>(addr);
781   return Result::Ok;
782 }
783 
784 template <typename MemType>
GetAtomicAccessAddress(const uint8_t ** pc,void ** out_address)785 Result Thread::GetAtomicAccessAddress(const uint8_t** pc, void** out_address) {
786   Memory* memory = ReadMemory(pc);
787   uint64_t addr = static_cast<uint64_t>(Pop<uint32_t>()) + ReadU32(pc);
788   TRAP_IF(addr + sizeof(MemType) > memory->data.size(),
789           MemoryAccessOutOfBounds);
790   TRAP_IF((addr & (sizeof(MemType) - 1)) != 0, AtomicMemoryAccessUnaligned);
791   *out_address = memory->data.data() + static_cast<IstreamOffset>(addr);
792   return Result::Ok;
793 }
794 
ReadDataSegment(const uint8_t ** pc)795 DataSegment* Thread::ReadDataSegment(const uint8_t** pc) {
796   Index index = ReadU32(pc);
797   assert(index < env_->data_segments_.size());
798   return &env_->data_segments_[index];
799 }
800 
ReadElemSegment(const uint8_t ** pc)801 ElemSegment* Thread::ReadElemSegment(const uint8_t** pc) {
802   Index index = ReadU32(pc);
803   assert(index < env_->elem_segments_.size());
804   return &env_->elem_segments_[index];
805 }
806 
Top()807 Value& Thread::Top() {
808   return Pick(1);
809 }
810 
Pick(Index depth)811 Value& Thread::Pick(Index depth) {
812   return value_stack_[value_stack_top_ - depth];
813 }
814 
Reset()815 void Thread::Reset() {
816   pc_ = 0;
817   value_stack_top_ = 0;
818   call_stack_top_ = 0;
819 }
820 
Push(Value value)821 Result Thread::Push(Value value) {
822   CHECK_STACK();
823   value_stack_[value_stack_top_++] = value;
824   return Result::Ok;
825 }
826 
Pop()827 Value Thread::Pop() {
828   return value_stack_[--value_stack_top_];
829 }
830 
ValueAt(Index at) const831 Value Thread::ValueAt(Index at) const {
832   assert(at < value_stack_top_);
833   return value_stack_[at];
834 }
835 
836 template <typename T>
Push(T value)837 Result Thread::Push(T value) {
838   return PushRep<T>(ToRep(value));
839 }
840 
841 template <typename T>
Pop()842 T Thread::Pop() {
843   return FromRep<T>(PopRep<T>());
844 }
845 
846 template <typename T>
PushRep(ValueTypeRep<T> value)847 Result Thread::PushRep(ValueTypeRep<T> value) {
848   return Push(MakeValue<T>(value));
849 }
850 
851 template <typename T>
PopRep()852 ValueTypeRep<T> Thread::PopRep() {
853   return GetValue<T>(Pop());
854 }
855 
DropKeep(uint32_t drop_count,uint32_t keep_count)856 void Thread::DropKeep(uint32_t drop_count, uint32_t keep_count) {
857   // Copy backward to avoid clobbering when the regions overlap.
858   for (uint32_t i = keep_count; i > 0; --i) {
859     Pick(drop_count + i) = Pick(i);
860   }
861   value_stack_top_ -= drop_count;
862 }
863 
PushCall(const uint8_t * pc)864 Result Thread::PushCall(const uint8_t* pc) {
865   TRAP_IF(call_stack_top_ >= call_stack_.size(), CallStackExhausted);
866   call_stack_[call_stack_top_++] = pc - GetIstream();
867   return Result::Ok;
868 }
869 
PopCall()870 IstreamOffset Thread::PopCall() {
871   return call_stack_[--call_stack_top_];
872 }
873 
874 template <typename T>
LoadFromMemory(T * dst,const void * src)875 void LoadFromMemory(T* dst, const void* src) {
876   memcpy(dst, src, sizeof(T));
877 }
878 
879 template <typename T>
StoreToMemory(void * dst,T value)880 void StoreToMemory(void* dst, T value) {
881   memcpy(dst, &value, sizeof(T));
882 }
883 
884 template <typename MemType, typename ResultType>
Load(const uint8_t ** pc)885 Result Thread::Load(const uint8_t** pc) {
886   typedef typename ExtendMemType<ResultType, MemType>::type ExtendedType;
887   static_assert(std::is_floating_point<MemType>::value ==
888                     std::is_floating_point<ExtendedType>::value,
889                 "Extended type should be float iff MemType is float");
890 
891   void* src;
892   CHECK_TRAP(GetAccessAddress<MemType>(pc, &src));
893   MemType value;
894   LoadFromMemory<MemType>(&value, src);
895   return Push<ResultType>(static_cast<ExtendedType>(value));
896 }
897 
898 template <typename MemType, typename ResultType>
Store(const uint8_t ** pc)899 Result Thread::Store(const uint8_t** pc) {
900   typedef typename WrapMemType<ResultType, MemType>::type WrappedType;
901   WrappedType value = PopRep<ResultType>();
902   void* dst;
903   CHECK_TRAP(GetAccessAddress<MemType>(pc, &dst));
904   StoreToMemory<WrappedType>(dst, value);
905   return Result::Ok;
906 }
907 
908 template <typename MemType, typename ResultType>
AtomicLoad(const uint8_t ** pc)909 Result Thread::AtomicLoad(const uint8_t** pc) {
910   typedef typename ExtendMemType<ResultType, MemType>::type ExtendedType;
911   static_assert(!std::is_floating_point<MemType>::value,
912                 "AtomicLoad type can't be float");
913   void* src;
914   CHECK_TRAP(GetAtomicAccessAddress<MemType>(pc, &src));
915   MemType value;
916   LoadFromMemory<MemType>(&value, src);
917   return Push<ResultType>(static_cast<ExtendedType>(value));
918 }
919 
920 template <typename MemType, typename ResultType>
AtomicStore(const uint8_t ** pc)921 Result Thread::AtomicStore(const uint8_t** pc) {
922   typedef typename WrapMemType<ResultType, MemType>::type WrappedType;
923   WrappedType value = PopRep<ResultType>();
924   void* dst;
925   CHECK_TRAP(GetAtomicAccessAddress<MemType>(pc, &dst));
926   StoreToMemory<WrappedType>(dst, value);
927   return Result::Ok;
928 }
929 
930 template <typename MemType, typename ResultType>
AtomicRmw(BinopFunc<ResultType,ResultType> func,const uint8_t ** pc)931 Result Thread::AtomicRmw(BinopFunc<ResultType, ResultType> func,
932                          const uint8_t** pc) {
933   typedef typename ExtendMemType<ResultType, MemType>::type ExtendedType;
934   MemType rhs = PopRep<ResultType>();
935   void* addr;
936   CHECK_TRAP(GetAtomicAccessAddress<MemType>(pc, &addr));
937   MemType read;
938   LoadFromMemory<MemType>(&read, addr);
939   StoreToMemory<MemType>(addr, func(read, rhs));
940   return Push<ResultType>(static_cast<ExtendedType>(read));
941 }
942 
943 template <typename MemType, typename ResultType>
AtomicRmwCmpxchg(const uint8_t ** pc)944 Result Thread::AtomicRmwCmpxchg(const uint8_t** pc) {
945   typedef typename ExtendMemType<ResultType, MemType>::type ExtendedType;
946   MemType replace = PopRep<ResultType>();
947   MemType expect = PopRep<ResultType>();
948   void* addr;
949   CHECK_TRAP(GetAtomicAccessAddress<MemType>(pc, &addr));
950   MemType read;
951   LoadFromMemory<MemType>(&read, addr);
952   if (read == expect) {
953     StoreToMemory<MemType>(addr, replace);
954   }
955   return Push<ResultType>(static_cast<ExtendedType>(read));
956 }
957 
ClampToBounds(uint32_t start,uint32_t * length,uint32_t max)958 bool ClampToBounds(uint32_t start, uint32_t* length, uint32_t max) {
959   if (start > max) {
960     *length = 0;
961     return false;
962   }
963   uint32_t avail = max - start;
964   if (*length > avail) {
965     *length = avail;
966     return false;
967   }
968   return true;
969 }
970 
MemoryInit(const uint8_t ** pc)971 Result Thread::MemoryInit(const uint8_t** pc) {
972   Memory* memory = ReadMemory(pc);
973   DataSegment* segment = ReadDataSegment(pc);
974   TRAP_IF(segment->dropped, DataSegmentDropped);
975   uint32_t memory_size = memory->data.size();
976   uint32_t segment_size = segment->data.size();
977   uint32_t size = Pop<uint32_t>();
978   uint32_t src = Pop<uint32_t>();
979   uint32_t dst = Pop<uint32_t>();
980   bool ok = ClampToBounds(dst, &size, memory_size);
981   ok &= ClampToBounds(src, &size, segment_size);
982   if (size > 0) {
983     memcpy(memory->data.data() + dst, segment->data.data() + src, size);
984   }
985   TRAP_IF(!ok, MemoryAccessOutOfBounds);
986   return Result::Ok;
987 }
988 
DataDrop(const uint8_t ** pc)989 Result Thread::DataDrop(const uint8_t** pc) {
990   DataSegment* segment = ReadDataSegment(pc);
991   TRAP_IF(segment->dropped, DataSegmentDropped);
992   segment->dropped = true;
993   return Result::Ok;
994 }
995 
MemoryCopy(const uint8_t ** pc)996 Result Thread::MemoryCopy(const uint8_t** pc) {
997   Memory* memory = ReadMemory(pc);
998   uint32_t memory_size = memory->data.size();
999   uint32_t size = Pop<uint32_t>();
1000   uint32_t src = Pop<uint32_t>();
1001   uint32_t dst = Pop<uint32_t>();
1002   bool copy_backward = src < dst && dst - src < size;
1003   bool ok = ClampToBounds(dst, &size, memory_size);
1004   // When copying backward, if the range is out-of-bounds, then no data will be
1005   // written.
1006   if (ok || !copy_backward) {
1007     ok &= ClampToBounds(src, &size, memory_size);
1008     if (size > 0) {
1009       char* data = memory->data.data();
1010       memmove(data + dst, data + src, size);
1011     }
1012   }
1013   TRAP_IF(!ok, MemoryAccessOutOfBounds);
1014   return Result::Ok;
1015 }
1016 
MemoryFill(const uint8_t ** pc)1017 Result Thread::MemoryFill(const uint8_t** pc) {
1018   Memory* memory = ReadMemory(pc);
1019   uint32_t memory_size = memory->data.size();
1020   uint32_t size = Pop<uint32_t>();
1021   uint8_t value = static_cast<uint8_t>(Pop<uint32_t>());
1022   uint32_t dst = Pop<uint32_t>();
1023   bool ok = ClampToBounds(dst, &size, memory_size);
1024   if (size > 0) {
1025     memset(memory->data.data() + dst, value, size);
1026   }
1027   TRAP_IF(!ok, MemoryAccessOutOfBounds);
1028   return Result::Ok;
1029 }
1030 
TableInit(const uint8_t ** pc)1031 Result Thread::TableInit(const uint8_t** pc) {
1032   Table* table = ReadTable(pc);
1033   ElemSegment* segment = ReadElemSegment(pc);
1034   TRAP_IF(segment->dropped, ElemSegmentDropped);
1035   uint32_t table_size = table->func_indexes.size();
1036   uint32_t segment_size = segment->elems.size();
1037   uint32_t size = Pop<uint32_t>();
1038   uint32_t src = Pop<uint32_t>();
1039   uint32_t dst = Pop<uint32_t>();
1040   bool ok = ClampToBounds(dst, &size, table_size);
1041   ok &= ClampToBounds(src, &size, segment_size);
1042   if (size > 0) {
1043     memcpy(table->func_indexes.data() + dst, segment->elems.data() + src,
1044            size * sizeof(table->func_indexes[0]));
1045   }
1046   TRAP_IF(!ok, TableAccessOutOfBounds);
1047   return Result::Ok;
1048 }
1049 
ElemDrop(const uint8_t ** pc)1050 Result Thread::ElemDrop(const uint8_t** pc) {
1051   ElemSegment* segment = ReadElemSegment(pc);
1052   TRAP_IF(segment->dropped, ElemSegmentDropped);
1053   segment->dropped = true;
1054   return Result::Ok;
1055 }
1056 
TableCopy(const uint8_t ** pc)1057 Result Thread::TableCopy(const uint8_t** pc) {
1058   Table* table = ReadTable(pc);
1059   uint32_t table_size = table->func_indexes.size();
1060   uint32_t size = Pop<uint32_t>();
1061   uint32_t src = Pop<uint32_t>();
1062   uint32_t dst = Pop<uint32_t>();
1063   bool copy_backward = src < dst && dst - src < size;
1064   bool ok = ClampToBounds(dst, &size, table_size);
1065   // When copying backward, if the range is out-of-bounds, then no data will be
1066   // written.
1067   if (ok || !copy_backward) {
1068     ok &= ClampToBounds(src, &size, table_size);
1069     if (size > 0) {
1070       Index* data = table->func_indexes.data();
1071       memmove(data + dst, data + src, size * sizeof(Index));
1072     }
1073   }
1074   TRAP_IF(!ok, TableAccessOutOfBounds);
1075   return Result::Ok;
1076 }
1077 
1078 template <typename R, typename T>
Unop(UnopFunc<R,T> func)1079 Result Thread::Unop(UnopFunc<R, T> func) {
1080   auto value = PopRep<T>();
1081   return PushRep<R>(func(value));
1082 }
1083 
1084 // {i8, i16, 132, i64}{16, 8, 4, 2}.(neg)
1085 template <typename T, typename L, typename R, typename P>
SimdUnop(UnopFunc<R,P> func)1086 Result Thread::SimdUnop(UnopFunc<R, P> func) {
1087   auto value = PopRep<T>();
1088 
1089   // Calculate how many Lanes according to input lane data type.
1090   constexpr int32_t lanes = sizeof(T) / sizeof(L);
1091 
1092   // Define SIMD data array for Simd add by Lanes.
1093   L simd_data_ret[lanes];
1094   L simd_data_0[lanes];
1095 
1096   // Convert intput SIMD data to array.
1097   memcpy(simd_data_0, &value, sizeof(T));
1098 
1099   // Constuct the Simd value by Lane data and Lane nums.
1100   for (int32_t i = 0; i < lanes; i++) {
1101     simd_data_ret[i] = static_cast<L>(func(simd_data_0[i]));
1102   }
1103 
1104   return PushRep<T>(Bitcast<T>(simd_data_ret));
1105 }
1106 
1107 template <typename R, typename T>
UnopTrap(UnopTrapFunc<R,T> func)1108 Result Thread::UnopTrap(UnopTrapFunc<R, T> func) {
1109   auto value = PopRep<T>();
1110   ValueTypeRep<R> result_value;
1111   CHECK_TRAP(func(value, &result_value));
1112   return PushRep<R>(result_value);
1113 }
1114 
1115 template <typename R, typename T>
Binop(BinopFunc<R,T> func)1116 Result Thread::Binop(BinopFunc<R, T> func) {
1117   auto rhs_rep = PopRep<T>();
1118   auto lhs_rep = PopRep<T>();
1119   return PushRep<R>(func(lhs_rep, rhs_rep));
1120 }
1121 
1122 // {i8, i16, 132, i64}{16, 8, 4, 2}.(add/sub/mul)
1123 template <typename T, typename L, typename R, typename P>
SimdBinop(BinopFunc<R,P> func)1124 Result Thread::SimdBinop(BinopFunc<R, P> func) {
1125   auto rhs_rep = PopRep<T>();
1126   auto lhs_rep = PopRep<T>();
1127 
1128   // Calculate how many Lanes according to input lane data type.
1129   constexpr int32_t lanes = sizeof(T) / sizeof(L);
1130 
1131   // Define SIMD data array for Simd add by Lanes.
1132   L simd_data_ret[lanes];
1133   L simd_data_0[lanes];
1134   L simd_data_1[lanes];
1135 
1136   // Convert intput SIMD data to array.
1137   memcpy(simd_data_0, &lhs_rep, sizeof(T));
1138   memcpy(simd_data_1, &rhs_rep, sizeof(T));
1139 
1140   // Constuct the Simd value by Lane data and Lane nums.
1141   for (int32_t i = 0; i < lanes; i++) {
1142     simd_data_ret[i] = static_cast<L>(func(simd_data_0[i], simd_data_1[i]));
1143   }
1144 
1145   return PushRep<T>(Bitcast<T>(simd_data_ret));
1146 }
1147 
1148 // {i8, i16, 132, i64, f32, f64}{16, 8, 4, 2}.(eq/ne/lt/le/gt/ge)
1149 template <typename T, typename L, typename R, typename P>
SimdRelBinop(BinopFunc<R,P> func)1150 Result Thread::SimdRelBinop(BinopFunc<R, P> func) {
1151   auto rhs_rep = PopRep<T>();
1152   auto lhs_rep = PopRep<T>();
1153 
1154   // Calculate how many Lanes according to input lane data type.
1155   constexpr int32_t lanes = sizeof(T) / sizeof(L);
1156 
1157   // Define SIMD data array for Simd add by Lanes.
1158   L simd_data_ret[lanes];
1159   L simd_data_0[lanes];
1160   L simd_data_1[lanes];
1161 
1162   // Convert intput SIMD data to array.
1163   memcpy(simd_data_0, &lhs_rep, sizeof(T));
1164   memcpy(simd_data_1, &rhs_rep, sizeof(T));
1165 
1166   // Constuct the Simd value by Lane data and Lane nums.
1167   for (int32_t i = 0; i < lanes; i++) {
1168     simd_data_ret[i] = static_cast<L>(
1169       func(simd_data_0[i], simd_data_1[i]) == 0? 0 : -1
1170     );
1171   }
1172 
1173   return PushRep<T>(Bitcast<T>(simd_data_ret));
1174 }
1175 
1176 template <typename R, typename T>
BinopTrap(BinopTrapFunc<R,T> func)1177 Result Thread::BinopTrap(BinopTrapFunc<R, T> func) {
1178   auto rhs_rep = PopRep<T>();
1179   auto lhs_rep = PopRep<T>();
1180   ValueTypeRep<R> result_value;
1181   CHECK_TRAP(func(lhs_rep, rhs_rep, &result_value));
1182   return PushRep<R>(result_value);
1183 }
1184 
1185 // {i,f}{32,64}.add
1186 template <typename T>
Add(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1187 ValueTypeRep<T> Add(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1188   return CanonicalizeNan<T>(ToRep(FromRep<T>(lhs_rep) + FromRep<T>(rhs_rep)));
1189 }
1190 
1191 template <typename T, typename R>
AddSaturate(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1192 ValueTypeRep<T> AddSaturate(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1193   T max = std::numeric_limits<R>::max();
1194   T min = std::numeric_limits<R>::min();
1195   T result = static_cast<T>(lhs_rep) + static_cast<T>(rhs_rep);
1196 
1197   if (result < min) {
1198     return ToRep(min);
1199   } else if (result > max) {
1200     return ToRep(max);
1201   } else {
1202     return ToRep(result);
1203   }
1204 }
1205 
1206 template <typename T, typename R>
SubSaturate(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1207 ValueTypeRep<T> SubSaturate(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1208   T max = std::numeric_limits<R>::max();
1209   T min = std::numeric_limits<R>::min();
1210   T result = static_cast<T>(lhs_rep) - static_cast<T>(rhs_rep);
1211 
1212   if (result < min) {
1213     return ToRep(min);
1214   } else if (result > max) {
1215     return ToRep(max);
1216   } else {
1217     return ToRep(result);
1218   }
1219 }
1220 
1221 template <typename T, typename L>
SimdIsLaneTrue(ValueTypeRep<T> value,int32_t true_cond)1222 int32_t SimdIsLaneTrue(ValueTypeRep<T> value, int32_t true_cond) {
1223   int true_count = 0;
1224 
1225   // Calculate how many Lanes according to input lane data type.
1226   constexpr int32_t lanes = sizeof(T) / sizeof(L);
1227 
1228   // Define SIMD data array for Simd Lanes.
1229   L simd_data_0[lanes];
1230 
1231   // Convert intput SIMD data to array.
1232   memcpy(simd_data_0, &value, sizeof(T));
1233 
1234   // Constuct the Simd value by Lane data and Lane nums.
1235   for (int32_t i = 0; i < lanes; i++) {
1236     if (simd_data_0[i] != 0)
1237       true_count++;
1238   }
1239 
1240   return (true_count >= true_cond) ? 1 : 0;
1241 }
1242 
1243 // {i,f}{32,64}.sub
1244 template <typename T>
Sub(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1245 ValueTypeRep<T> Sub(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1246   return CanonicalizeNan<T>(ToRep(FromRep<T>(lhs_rep) - FromRep<T>(rhs_rep)));
1247 }
1248 
1249 // {i,f}{32,64}.mul
1250 template <typename T>
Mul(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1251 ValueTypeRep<T> Mul(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1252   return CanonicalizeNan<T>(ToRep(FromRep<T>(lhs_rep) * FromRep<T>(rhs_rep)));
1253 }
1254 
1255 // i{32,64}.{div,rem}_s are special-cased because they trap when dividing the
1256 // max signed value by -1. The modulo operation on x86 uses the same
1257 // instruction to generate the quotient and the remainder.
1258 template <typename T>
IsNormalDivRemS(T lhs,T rhs)1259 bool IsNormalDivRemS(T lhs, T rhs) {
1260   static_assert(std::is_signed<T>::value, "T should be a signed type.");
1261   return !(lhs == std::numeric_limits<T>::min() && rhs == -1);
1262 }
1263 
1264 // i{32,64}.div_s
1265 template <typename T>
IntDivS(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep,ValueTypeRep<T> * out_result)1266 Result IntDivS(ValueTypeRep<T> lhs_rep,
1267                ValueTypeRep<T> rhs_rep,
1268                ValueTypeRep<T>* out_result) {
1269   auto lhs = FromRep<T>(lhs_rep);
1270   auto rhs = FromRep<T>(rhs_rep);
1271   TRAP_IF(rhs == 0, IntegerDivideByZero);
1272   TRAP_UNLESS(IsNormalDivRemS(lhs, rhs), IntegerOverflow);
1273   *out_result = ToRep(lhs / rhs);
1274   return Result::Ok;
1275 }
1276 
1277 // i{32,64}.rem_s
1278 template <typename T>
IntRemS(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep,ValueTypeRep<T> * out_result)1279 Result IntRemS(ValueTypeRep<T> lhs_rep,
1280                ValueTypeRep<T> rhs_rep,
1281                ValueTypeRep<T>* out_result) {
1282   auto lhs = FromRep<T>(lhs_rep);
1283   auto rhs = FromRep<T>(rhs_rep);
1284   TRAP_IF(rhs == 0, IntegerDivideByZero);
1285   if (WABT_LIKELY(IsNormalDivRemS(lhs, rhs))) {
1286     *out_result = ToRep(lhs % rhs);
1287   } else {
1288     *out_result = 0;
1289   }
1290   return Result::Ok;
1291 }
1292 
1293 // i{32,64}.div_u
1294 template <typename T>
IntDivU(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep,ValueTypeRep<T> * out_result)1295 Result IntDivU(ValueTypeRep<T> lhs_rep,
1296                ValueTypeRep<T> rhs_rep,
1297                ValueTypeRep<T>* out_result) {
1298   auto lhs = FromRep<T>(lhs_rep);
1299   auto rhs = FromRep<T>(rhs_rep);
1300   TRAP_IF(rhs == 0, IntegerDivideByZero);
1301   *out_result = ToRep(lhs / rhs);
1302   return Result::Ok;
1303 }
1304 
1305 // i{32,64}.rem_u
1306 template <typename T>
IntRemU(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep,ValueTypeRep<T> * out_result)1307 Result IntRemU(ValueTypeRep<T> lhs_rep,
1308                ValueTypeRep<T> rhs_rep,
1309                ValueTypeRep<T>* out_result) {
1310   auto lhs = FromRep<T>(lhs_rep);
1311   auto rhs = FromRep<T>(rhs_rep);
1312   TRAP_IF(rhs == 0, IntegerDivideByZero);
1313   *out_result = ToRep(lhs % rhs);
1314   return Result::Ok;
1315 }
1316 
1317 // f{32,64}.div
1318 template <typename T>
FloatDiv(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1319 ValueTypeRep<T> FloatDiv(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1320   typedef FloatTraits<T> Traits;
1321   ValueTypeRep<T> result;
1322   if (WABT_UNLIKELY(Traits::IsZero(rhs_rep))) {
1323     if (Traits::IsNan(lhs_rep) || Traits::IsZero(lhs_rep)) {
1324       result = Traits::kQuietNan;
1325     } else {
1326       auto sign = (lhs_rep & Traits::kSignMask) ^ (rhs_rep & Traits::kSignMask);
1327       result = sign | Traits::kInf;
1328     }
1329   } else {
1330     result =
1331         CanonicalizeNan<T>(ToRep(FromRep<T>(lhs_rep) / FromRep<T>(rhs_rep)));
1332   }
1333   return result;
1334 }
1335 
1336 // i{32,64}.and
1337 template <typename T>
IntAnd(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1338 ValueTypeRep<T> IntAnd(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1339   return ToRep(FromRep<T>(lhs_rep) & FromRep<T>(rhs_rep));
1340 }
1341 
1342 // i{32,64}.or
1343 template <typename T>
IntOr(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1344 ValueTypeRep<T> IntOr(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1345   return ToRep(FromRep<T>(lhs_rep) | FromRep<T>(rhs_rep));
1346 }
1347 
1348 // i{32,64}.xor
1349 template <typename T>
IntXor(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1350 ValueTypeRep<T> IntXor(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1351   return ToRep(FromRep<T>(lhs_rep) ^ FromRep<T>(rhs_rep));
1352 }
1353 
1354 // i{32,64}.shl
1355 template <typename T>
IntShl(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1356 ValueTypeRep<T> IntShl(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1357   const int mask = sizeof(T) * 8 - 1;
1358   return ToRep(FromRep<T>(lhs_rep) << (FromRep<T>(rhs_rep) & mask));
1359 }
1360 
1361 // i{32,64}.shr_{s,u}
1362 template <typename T>
IntShr(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1363 ValueTypeRep<T> IntShr(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1364   const int mask = sizeof(T) * 8 - 1;
1365   return ToRep(FromRep<T>(lhs_rep) >> (FromRep<T>(rhs_rep) & mask));
1366 }
1367 
1368 // i{32,64}.rotl
1369 template <typename T>
IntRotl(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1370 ValueTypeRep<T> IntRotl(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1371   const int mask = sizeof(T) * 8 - 1;
1372   int amount = FromRep<T>(rhs_rep) & mask;
1373   auto lhs = FromRep<T>(lhs_rep);
1374   if (amount == 0) {
1375     return ToRep(lhs);
1376   } else {
1377     return ToRep((lhs << amount) | (lhs >> (mask + 1 - amount)));
1378   }
1379 }
1380 
1381 // i{32,64}.rotr
1382 template <typename T>
IntRotr(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1383 ValueTypeRep<T> IntRotr(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1384   const int mask = sizeof(T) * 8 - 1;
1385   int amount = FromRep<T>(rhs_rep) & mask;
1386   auto lhs = FromRep<T>(lhs_rep);
1387   if (amount == 0) {
1388     return ToRep(lhs);
1389   } else {
1390     return ToRep((lhs >> amount) | (lhs << (mask + 1 - amount)));
1391   }
1392 }
1393 
1394 // i{32,64}.eqz
1395 template <typename R, typename T>
IntEqz(ValueTypeRep<T> v_rep)1396 ValueTypeRep<R> IntEqz(ValueTypeRep<T> v_rep) {
1397   return ToRep(v_rep == 0);
1398 }
1399 
1400 template <typename T>
IntNeg(ValueTypeRep<T> v_rep)1401 ValueTypeRep<T> IntNeg(ValueTypeRep<T> v_rep) {
1402   T tmp = static_cast<T>(v_rep);
1403   return ToRep(-tmp);
1404 }
1405 
1406 template <typename T>
IntNot(ValueTypeRep<T> v_rep)1407 ValueTypeRep<T> IntNot(ValueTypeRep<T> v_rep) {
1408   T tmp = static_cast<T>(v_rep);
1409   return ToRep(~tmp);
1410 }
1411 
1412 // f{32,64}.abs
1413 template <typename T>
FloatAbs(ValueTypeRep<T> v_rep)1414 ValueTypeRep<T> FloatAbs(ValueTypeRep<T> v_rep) {
1415   return v_rep & ~FloatTraits<T>::kSignMask;
1416 }
1417 
1418 // f{32,64}.neg
1419 template <typename T>
FloatNeg(ValueTypeRep<T> v_rep)1420 ValueTypeRep<T> FloatNeg(ValueTypeRep<T> v_rep) {
1421   return v_rep ^ FloatTraits<T>::kSignMask;
1422 }
1423 
1424 // f{32,64}.ceil
1425 template <typename T>
FloatCeil(ValueTypeRep<T> v_rep)1426 ValueTypeRep<T> FloatCeil(ValueTypeRep<T> v_rep) {
1427   return CanonicalizeNan<T>(ToRep(std::ceil(FromRep<T>(v_rep))));
1428 }
1429 
1430 // f{32,64}.floor
1431 template <typename T>
FloatFloor(ValueTypeRep<T> v_rep)1432 ValueTypeRep<T> FloatFloor(ValueTypeRep<T> v_rep) {
1433   return CanonicalizeNan<T>(ToRep(std::floor(FromRep<T>(v_rep))));
1434 }
1435 
1436 // f{32,64}.trunc
1437 template <typename T>
FloatTrunc(ValueTypeRep<T> v_rep)1438 ValueTypeRep<T> FloatTrunc(ValueTypeRep<T> v_rep) {
1439   return CanonicalizeNan<T>(ToRep(std::trunc(FromRep<T>(v_rep))));
1440 }
1441 
1442 // f{32,64}.nearest
1443 template <typename T>
FloatNearest(ValueTypeRep<T> v_rep)1444 ValueTypeRep<T> FloatNearest(ValueTypeRep<T> v_rep) {
1445   return CanonicalizeNan<T>(ToRep(std::nearbyint(FromRep<T>(v_rep))));
1446 }
1447 
1448 // f{32,64}.sqrt
1449 template <typename T>
FloatSqrt(ValueTypeRep<T> v_rep)1450 ValueTypeRep<T> FloatSqrt(ValueTypeRep<T> v_rep) {
1451   return CanonicalizeNan<T>(ToRep(std::sqrt(FromRep<T>(v_rep))));
1452 }
1453 
1454 // f{32,64}.min
1455 template <typename T>
FloatMin(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1456 ValueTypeRep<T> FloatMin(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1457   typedef FloatTraits<T> Traits;
1458 
1459   if (WABT_UNLIKELY(Traits::IsNan(lhs_rep) || Traits::IsNan(rhs_rep))) {
1460     return Traits::kQuietNan;
1461   } else if (WABT_UNLIKELY(Traits::IsZero(lhs_rep) &&
1462                            Traits::IsZero(rhs_rep))) {
1463     // min(0.0, -0.0) == -0.0, but std::min won't produce the correct result.
1464     // We can instead compare using the unsigned integer representation, but
1465     // just max instead (since the sign bit makes the value larger).
1466     return std::max(lhs_rep, rhs_rep);
1467   } else {
1468     return ToRep(std::min(FromRep<T>(lhs_rep), FromRep<T>(rhs_rep)));
1469   }
1470 }
1471 
1472 // f{32,64}.max
1473 template <typename T>
FloatMax(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1474 ValueTypeRep<T> FloatMax(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1475   typedef FloatTraits<T> Traits;
1476 
1477   if (WABT_UNLIKELY(Traits::IsNan(lhs_rep) || Traits::IsNan(rhs_rep))) {
1478     return Traits::kQuietNan;
1479   } else if (WABT_UNLIKELY(Traits::IsZero(lhs_rep) &&
1480                            Traits::IsZero(rhs_rep))) {
1481     // min(0.0, -0.0) == -0.0, but std::min won't produce the correct result.
1482     // We can instead compare using the unsigned integer representation, but
1483     // just max instead (since the sign bit makes the value larger).
1484     return std::min(lhs_rep, rhs_rep);
1485   } else {
1486     return ToRep(std::max(FromRep<T>(lhs_rep), FromRep<T>(rhs_rep)));
1487   }
1488 }
1489 
1490 // f{32,64}.copysign
1491 template <typename T>
FloatCopySign(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1492 ValueTypeRep<T> FloatCopySign(ValueTypeRep<T> lhs_rep,
1493                               ValueTypeRep<T> rhs_rep) {
1494   typedef FloatTraits<T> Traits;
1495   return (lhs_rep & ~Traits::kSignMask) | (rhs_rep & Traits::kSignMask);
1496 }
1497 
1498 // {i,f}{32,64}.eq
1499 template <typename T>
Eq(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1500 uint32_t Eq(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1501   return ToRep(FromRep<T>(lhs_rep) == FromRep<T>(rhs_rep));
1502 }
1503 
1504 // {i,f}{32,64}.ne
1505 template <typename T>
Ne(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1506 uint32_t Ne(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1507   return ToRep(FromRep<T>(lhs_rep) != FromRep<T>(rhs_rep));
1508 }
1509 
1510 // f{32,64}.lt | i{32,64}.lt_{s,u}
1511 template <typename T>
Lt(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1512 uint32_t Lt(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1513   return ToRep(FromRep<T>(lhs_rep) < FromRep<T>(rhs_rep));
1514 }
1515 
1516 // f{32,64}.le | i{32,64}.le_{s,u}
1517 template <typename T>
Le(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1518 uint32_t Le(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1519   return ToRep(FromRep<T>(lhs_rep) <= FromRep<T>(rhs_rep));
1520 }
1521 
1522 // f{32,64}.gt | i{32,64}.gt_{s,u}
1523 template <typename T>
Gt(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1524 uint32_t Gt(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1525   return ToRep(FromRep<T>(lhs_rep) > FromRep<T>(rhs_rep));
1526 }
1527 
1528 // f{32,64}.ge | i{32,64}.ge_{s,u}
1529 template <typename T>
Ge(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1530 uint32_t Ge(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1531   return ToRep(FromRep<T>(lhs_rep) >= FromRep<T>(rhs_rep));
1532 }
1533 
1534 // f32x4.convert_{s,u}/i32x4 and f64x2.convert_s/i64x2.
1535 template <typename R, typename T>
SimdConvert(ValueTypeRep<T> v_rep)1536 ValueTypeRep<R> SimdConvert(ValueTypeRep<T> v_rep) {
1537   return ToRep(static_cast<R>(static_cast<T>(v_rep)));
1538 }
1539 
1540 // f64x2.convert_u/i64x2 use this instance due to MSVC issue.
1541 template <>
SimdConvert(ValueTypeRep<uint64_t> v_rep)1542 ValueTypeRep<double> SimdConvert<double, uint64_t>(
1543     ValueTypeRep<uint64_t> v_rep) {
1544   return ToRep(wabt_convert_uint64_to_double(v_rep));
1545 }
1546 
1547 // i{32,64}.trunc_{s,u}/f{32,64}
1548 template <typename R, typename T>
IntTrunc(ValueTypeRep<T> v_rep,ValueTypeRep<R> * out_result)1549 Result IntTrunc(ValueTypeRep<T> v_rep, ValueTypeRep<R>* out_result) {
1550   TRAP_IF(FloatTraits<T>::IsNan(v_rep), InvalidConversionToInteger);
1551   TRAP_UNLESS((IsConversionInRange<R, T>(v_rep)), IntegerOverflow);
1552   *out_result = ToRep(static_cast<R>(FromRep<T>(v_rep)));
1553   return Result::Ok;
1554 }
1555 
1556 // i{32,64}.trunc_{s,u}:sat/f{32,64}
1557 template <typename R, typename T>
IntTruncSat(ValueTypeRep<T> v_rep)1558 ValueTypeRep<R> IntTruncSat(ValueTypeRep<T> v_rep) {
1559   typedef FloatTraits<T> Traits;
1560   if (WABT_UNLIKELY(Traits::IsNan(v_rep))) {
1561     return 0;
1562   } else if (WABT_UNLIKELY((!IsConversionInRange<R, T>(v_rep)))) {
1563     if (v_rep & Traits::kSignMask) {
1564       return ToRep(std::numeric_limits<R>::min());
1565     } else {
1566       return ToRep(std::numeric_limits<R>::max());
1567     }
1568   } else {
1569     return ToRep(static_cast<R>(FromRep<T>(v_rep)));
1570   }
1571 }
1572 
1573 // i{32,64}.extend{8,16,32}_s
1574 template <typename T, typename E>
IntExtendS(ValueTypeRep<T> v_rep)1575 ValueTypeRep<T> IntExtendS(ValueTypeRep<T> v_rep) {
1576   // To avoid undefined/implementation-defined behavior, convert from unsigned
1577   // type (T), to an unsigned value of the smaller size (EU), then bitcast from
1578   // unsigned to signed, then cast from the smaller signed type to the larger
1579   // signed type (TS) to sign extend. ToRep then will bitcast back from signed
1580   // to unsigned.
1581   static_assert(std::is_unsigned<ValueTypeRep<T>>::value, "T must be unsigned");
1582   static_assert(std::is_signed<E>::value, "E must be signed");
1583   typedef typename std::make_unsigned<E>::type EU;
1584   typedef typename std::make_signed<T>::type TS;
1585   return ToRep(static_cast<TS>(Bitcast<E>(static_cast<EU>(v_rep))));
1586 }
1587 
1588 // i{32,64}.atomic.rmw(8,16,32}_u.xchg
1589 template <typename T>
Xchg(ValueTypeRep<T> lhs_rep,ValueTypeRep<T> rhs_rep)1590 ValueTypeRep<T> Xchg(ValueTypeRep<T> lhs_rep, ValueTypeRep<T> rhs_rep) {
1591   return rhs_rep;
1592 }
1593 
1594 // i(8,16,32,64) f(32,64) X (2,4,8,16) splat ==> v128
1595 template <typename T, typename V>
SimdSplat(V lane_data)1596 ValueTypeRep<T> SimdSplat(V lane_data) {
1597   // Calculate how many Lanes according to input lane data type.
1598   int32_t lanes = sizeof(T) / sizeof(V);
1599 
1600   // Define SIMD data array by Lanes.
1601   V simd_data[sizeof(T) / sizeof(V)];
1602 
1603   // Constuct the Simd value by Land data and Lane nums.
1604   for (int32_t i = 0; i < lanes; i++) {
1605     simd_data[i] = lane_data;
1606   }
1607 
1608   return ToRep(Bitcast<T>(simd_data));
1609 }
1610 
1611 // Simd instructions of Lane extract.
1612 // value: input v128 value.
1613 // typename T: lane data type.
1614 template <typename R, typename V, typename T>
SimdExtractLane(V value,uint32_t laneidx)1615 ValueTypeRep<R> SimdExtractLane(V value, uint32_t laneidx) {
1616   // Calculate how many Lanes according to input lane data type.
1617   constexpr int32_t lanes = sizeof(V) / sizeof(T);
1618 
1619   // Define SIMD data array for Simd add by Lanes.
1620   T simd_data_0[lanes];
1621 
1622   // Convert intput SIMD data to array.
1623   memcpy(simd_data_0, &value, sizeof(V));
1624 
1625   return ToRep(static_cast<R>(simd_data_0[laneidx]));
1626 }
1627 
1628 // Simd instructions of Lane replace.
1629 // value: input v128 value.  lane_val: input lane data.
1630 // typename T: lane data type.
1631 template <typename R, typename V, typename T>
SimdReplaceLane(V value,uint32_t lane_idx,T lane_val)1632 ValueTypeRep<R> SimdReplaceLane(V value, uint32_t lane_idx, T lane_val) {
1633   // Calculate how many Lanes according to input lane data type.
1634   constexpr int32_t lanes = sizeof(V) / sizeof(T);
1635 
1636   // Define SIMD data array for Simd add by Lanes.
1637   T simd_data_0[lanes];
1638 
1639   // Convert intput SIMD data to array.
1640   memcpy(simd_data_0, &value, sizeof(V));
1641 
1642   // Replace the indicated lane.
1643   simd_data_0[lane_idx] = lane_val;
1644 
1645   return ToRep(Bitcast<R>(simd_data_0));
1646 }
1647 
FuncSignaturesAreEqual(Index sig_index_0,Index sig_index_1) const1648 bool Environment::FuncSignaturesAreEqual(Index sig_index_0,
1649                                          Index sig_index_1) const {
1650   if (sig_index_0 == sig_index_1) {
1651     return true;
1652   }
1653   const FuncSignature* sig_0 = &sigs_[sig_index_0];
1654   const FuncSignature* sig_1 = &sigs_[sig_index_1];
1655   return sig_0->param_types == sig_1->param_types &&
1656          sig_0->result_types == sig_1->result_types;
1657 }
1658 
CallHost(HostFunc * func)1659 Result Thread::CallHost(HostFunc* func) {
1660   FuncSignature* sig = &env_->sigs_[func->sig_index];
1661 
1662   size_t num_params = sig->param_types.size();
1663   size_t num_results = sig->result_types.size();
1664   TypedValues params(num_params);
1665   TypedValues results(num_results);
1666 
1667   for (size_t i = num_params; i > 0; --i) {
1668     params[i - 1].value = Pop();
1669     params[i - 1].type = sig->param_types[i - 1];
1670   }
1671 
1672   for (size_t i = 0; i < num_results; ++i) {
1673     results[i].type = sig->result_types[i];
1674     results[i].SetZero();
1675   }
1676 
1677   Result call_result = func->callback(func, sig, params, results);
1678   TRAP_IF(call_result != Result::Ok, HostTrapped);
1679 
1680   TRAP_IF(results.size() != num_results, HostResultTypeMismatch);
1681   for (size_t i = 0; i < num_results; ++i) {
1682     TRAP_IF(results[i].type != sig->result_types[i], HostResultTypeMismatch);
1683     CHECK_TRAP(Push(results[i].value));
1684   }
1685 
1686   return Result::Ok;
1687 }
1688 
Run(int num_instructions)1689 Result Thread::Run(int num_instructions) {
1690   Result result = Result::Ok;
1691 
1692   const uint8_t* istream = GetIstream();
1693   const uint8_t* pc = &istream[pc_];
1694   for (int i = 0; i < num_instructions; ++i) {
1695     Opcode opcode = ReadOpcode(&pc);
1696     assert(!opcode.IsInvalid());
1697     switch (opcode) {
1698       case Opcode::Select: {
1699         uint32_t cond = Pop<uint32_t>();
1700         Value false_ = Pop();
1701         Value true_ = Pop();
1702         CHECK_TRAP(Push(cond ? true_ : false_));
1703         break;
1704       }
1705 
1706       case Opcode::Br:
1707         GOTO(ReadU32(&pc));
1708         break;
1709 
1710       case Opcode::BrIf: {
1711         IstreamOffset new_pc = ReadU32(&pc);
1712         if (Pop<uint32_t>()) {
1713           GOTO(new_pc);
1714         }
1715         break;
1716       }
1717 
1718       case Opcode::BrTable: {
1719         Index num_targets = ReadU32(&pc);
1720         IstreamOffset table_offset = ReadU32(&pc);
1721         uint32_t key = Pop<uint32_t>();
1722         IstreamOffset key_offset =
1723             (key >= num_targets ? num_targets : key) * WABT_TABLE_ENTRY_SIZE;
1724         const uint8_t* entry = istream + table_offset + key_offset;
1725         IstreamOffset new_pc;
1726         uint32_t drop_count;
1727         uint32_t keep_count;
1728         ReadTableEntryAt(entry, &new_pc, &drop_count, &keep_count);
1729         DropKeep(drop_count, keep_count);
1730         GOTO(new_pc);
1731         break;
1732       }
1733 
1734       case Opcode::Return:
1735         if (call_stack_top_ == 0) {
1736           result = Result::Returned;
1737           goto exit_loop;
1738         }
1739         GOTO(PopCall());
1740         break;
1741 
1742       case Opcode::Unreachable:
1743         TRAP(Unreachable);
1744         break;
1745 
1746       case Opcode::I32Const:
1747         CHECK_TRAP(Push<uint32_t>(ReadU32(&pc)));
1748         break;
1749 
1750       case Opcode::I64Const:
1751         CHECK_TRAP(Push<uint64_t>(ReadU64(&pc)));
1752         break;
1753 
1754       case Opcode::F32Const:
1755         CHECK_TRAP(PushRep<float>(ReadU32(&pc)));
1756         break;
1757 
1758       case Opcode::F64Const:
1759         CHECK_TRAP(PushRep<double>(ReadU64(&pc)));
1760         break;
1761 
1762       case Opcode::GlobalGet: {
1763         Index index = ReadU32(&pc);
1764         assert(index < env_->globals_.size());
1765         CHECK_TRAP(Push(env_->globals_[index].typed_value.value));
1766         break;
1767       }
1768 
1769       case Opcode::GlobalSet: {
1770         Index index = ReadU32(&pc);
1771         assert(index < env_->globals_.size());
1772         env_->globals_[index].typed_value.value = Pop();
1773         break;
1774       }
1775 
1776       case Opcode::LocalGet: {
1777         Value value = Pick(ReadU32(&pc));
1778         CHECK_TRAP(Push(value));
1779         break;
1780       }
1781 
1782       case Opcode::LocalSet: {
1783         Value value = Pop();
1784         Pick(ReadU32(&pc)) = value;
1785         break;
1786       }
1787 
1788       case Opcode::LocalTee:
1789         Pick(ReadU32(&pc)) = Top();
1790         break;
1791 
1792       case Opcode::Call: {
1793         IstreamOffset offset = ReadU32(&pc);
1794         CHECK_TRAP(PushCall(pc));
1795         GOTO(offset);
1796         break;
1797       }
1798 
1799       case Opcode::CallIndirect: {
1800         Table* table = ReadTable(&pc);
1801         Index sig_index = ReadU32(&pc);
1802         Index entry_index = Pop<uint32_t>();
1803         TRAP_IF(entry_index >= table->func_indexes.size(), UndefinedTableIndex);
1804         Index func_index = table->func_indexes[entry_index];
1805         TRAP_IF(func_index == kInvalidIndex, UninitializedTableElement);
1806         Func* func = env_->funcs_[func_index].get();
1807         TRAP_UNLESS(env_->FuncSignaturesAreEqual(func->sig_index, sig_index),
1808                     IndirectCallSignatureMismatch);
1809         if (func->is_host) {
1810           CHECK_TRAP(CallHost(cast<HostFunc>(func)));
1811         } else {
1812           CHECK_TRAP(PushCall(pc));
1813           GOTO(cast<DefinedFunc>(func)->offset);
1814         }
1815         break;
1816       }
1817 
1818       case Opcode::InterpCallHost: {
1819         Index func_index = ReadU32(&pc);
1820         CHECK_TRAP(CallHost(cast<HostFunc>(env_->funcs_[func_index].get())));
1821         break;
1822       }
1823 
1824       case Opcode::ReturnCall: {
1825         IstreamOffset offset = ReadU32(&pc);
1826         GOTO(offset);
1827 
1828         break;
1829       }
1830 
1831       case Opcode::ReturnCallIndirect:{
1832         Table* table = ReadTable(&pc);
1833         Index sig_index = ReadU32(&pc);
1834         Index entry_index = Pop<uint32_t>();
1835         TRAP_IF(entry_index >= table->func_indexes.size(), UndefinedTableIndex);
1836         Index func_index = table->func_indexes[entry_index];
1837         TRAP_IF(func_index == kInvalidIndex, UninitializedTableElement);
1838         Func* func = env_->funcs_[func_index].get();
1839         TRAP_UNLESS(env_->FuncSignaturesAreEqual(func->sig_index, sig_index),
1840                     IndirectCallSignatureMismatch);
1841         if (func->is_host) { // Emulate a call/return for imported functions
1842           CHECK_TRAP(CallHost(cast<HostFunc>(func)));
1843           if (call_stack_top_ == 0) {
1844             result = Result::Returned;
1845             goto exit_loop;
1846           }
1847           GOTO(PopCall());
1848         } else {
1849           GOTO(cast<DefinedFunc>(func)->offset);
1850         }
1851         break;
1852       }
1853 
1854       case Opcode::I32Load8S:
1855         CHECK_TRAP(Load<int8_t, uint32_t>(&pc));
1856         break;
1857 
1858       case Opcode::I32Load8U:
1859         CHECK_TRAP(Load<uint8_t, uint32_t>(&pc));
1860         break;
1861 
1862       case Opcode::I32Load16S:
1863         CHECK_TRAP(Load<int16_t, uint32_t>(&pc));
1864         break;
1865 
1866       case Opcode::I32Load16U:
1867         CHECK_TRAP(Load<uint16_t, uint32_t>(&pc));
1868         break;
1869 
1870       case Opcode::I64Load8S:
1871         CHECK_TRAP(Load<int8_t, uint64_t>(&pc));
1872         break;
1873 
1874       case Opcode::I64Load8U:
1875         CHECK_TRAP(Load<uint8_t, uint64_t>(&pc));
1876         break;
1877 
1878       case Opcode::I64Load16S:
1879         CHECK_TRAP(Load<int16_t, uint64_t>(&pc));
1880         break;
1881 
1882       case Opcode::I64Load16U:
1883         CHECK_TRAP(Load<uint16_t, uint64_t>(&pc));
1884         break;
1885 
1886       case Opcode::I64Load32S:
1887         CHECK_TRAP(Load<int32_t, uint64_t>(&pc));
1888         break;
1889 
1890       case Opcode::I64Load32U:
1891         CHECK_TRAP(Load<uint32_t, uint64_t>(&pc));
1892         break;
1893 
1894       case Opcode::I32Load:
1895         CHECK_TRAP(Load<uint32_t>(&pc));
1896         break;
1897 
1898       case Opcode::I64Load:
1899         CHECK_TRAP(Load<uint64_t>(&pc));
1900         break;
1901 
1902       case Opcode::F32Load:
1903         CHECK_TRAP(Load<float>(&pc));
1904         break;
1905 
1906       case Opcode::F64Load:
1907         CHECK_TRAP(Load<double>(&pc));
1908         break;
1909 
1910       case Opcode::I32Store8:
1911         CHECK_TRAP(Store<uint8_t, uint32_t>(&pc));
1912         break;
1913 
1914       case Opcode::I32Store16:
1915         CHECK_TRAP(Store<uint16_t, uint32_t>(&pc));
1916         break;
1917 
1918       case Opcode::I64Store8:
1919         CHECK_TRAP(Store<uint8_t, uint64_t>(&pc));
1920         break;
1921 
1922       case Opcode::I64Store16:
1923         CHECK_TRAP(Store<uint16_t, uint64_t>(&pc));
1924         break;
1925 
1926       case Opcode::I64Store32:
1927         CHECK_TRAP(Store<uint32_t, uint64_t>(&pc));
1928         break;
1929 
1930       case Opcode::I32Store:
1931         CHECK_TRAP(Store<uint32_t>(&pc));
1932         break;
1933 
1934       case Opcode::I64Store:
1935         CHECK_TRAP(Store<uint64_t>(&pc));
1936         break;
1937 
1938       case Opcode::F32Store:
1939         CHECK_TRAP(Store<float>(&pc));
1940         break;
1941 
1942       case Opcode::F64Store:
1943         CHECK_TRAP(Store<double>(&pc));
1944         break;
1945 
1946       case Opcode::I32AtomicLoad8U:
1947         CHECK_TRAP(AtomicLoad<uint8_t, uint32_t>(&pc));
1948         break;
1949 
1950       case Opcode::I32AtomicLoad16U:
1951         CHECK_TRAP(AtomicLoad<uint16_t, uint32_t>(&pc));
1952         break;
1953 
1954       case Opcode::I64AtomicLoad8U:
1955         CHECK_TRAP(AtomicLoad<uint8_t, uint64_t>(&pc));
1956         break;
1957 
1958       case Opcode::I64AtomicLoad16U:
1959         CHECK_TRAP(AtomicLoad<uint16_t, uint64_t>(&pc));
1960         break;
1961 
1962       case Opcode::I64AtomicLoad32U:
1963         CHECK_TRAP(AtomicLoad<uint32_t, uint64_t>(&pc));
1964         break;
1965 
1966       case Opcode::I32AtomicLoad:
1967         CHECK_TRAP(AtomicLoad<uint32_t>(&pc));
1968         break;
1969 
1970       case Opcode::I64AtomicLoad:
1971         CHECK_TRAP(AtomicLoad<uint64_t>(&pc));
1972         break;
1973 
1974       case Opcode::I32AtomicStore8:
1975         CHECK_TRAP(AtomicStore<uint8_t, uint32_t>(&pc));
1976         break;
1977 
1978       case Opcode::I32AtomicStore16:
1979         CHECK_TRAP(AtomicStore<uint16_t, uint32_t>(&pc));
1980         break;
1981 
1982       case Opcode::I64AtomicStore8:
1983         CHECK_TRAP(AtomicStore<uint8_t, uint64_t>(&pc));
1984         break;
1985 
1986       case Opcode::I64AtomicStore16:
1987         CHECK_TRAP(AtomicStore<uint16_t, uint64_t>(&pc));
1988         break;
1989 
1990       case Opcode::I64AtomicStore32:
1991         CHECK_TRAP(AtomicStore<uint32_t, uint64_t>(&pc));
1992         break;
1993 
1994       case Opcode::I32AtomicStore:
1995         CHECK_TRAP(AtomicStore<uint32_t>(&pc));
1996         break;
1997 
1998       case Opcode::I64AtomicStore:
1999         CHECK_TRAP(AtomicStore<uint64_t>(&pc));
2000         break;
2001 
2002 #define ATOMIC_RMW(rmwop, func)                                     \
2003   case Opcode::I32AtomicRmw##rmwop:                                 \
2004     CHECK_TRAP(AtomicRmw<uint32_t, uint32_t>(func<uint32_t>, &pc)); \
2005     break;                                                          \
2006   case Opcode::I64AtomicRmw##rmwop:                                 \
2007     CHECK_TRAP(AtomicRmw<uint64_t, uint64_t>(func<uint64_t>, &pc)); \
2008     break;                                                          \
2009   case Opcode::I32AtomicRmw8##rmwop##U:                             \
2010     CHECK_TRAP(AtomicRmw<uint8_t, uint32_t>(func<uint32_t>, &pc));  \
2011     break;                                                          \
2012   case Opcode::I32AtomicRmw16##rmwop##U:                            \
2013     CHECK_TRAP(AtomicRmw<uint16_t, uint32_t>(func<uint32_t>, &pc)); \
2014     break;                                                          \
2015   case Opcode::I64AtomicRmw8##rmwop##U:                             \
2016     CHECK_TRAP(AtomicRmw<uint8_t, uint64_t>(func<uint64_t>, &pc));  \
2017     break;                                                          \
2018   case Opcode::I64AtomicRmw16##rmwop##U:                            \
2019     CHECK_TRAP(AtomicRmw<uint16_t, uint64_t>(func<uint64_t>, &pc)); \
2020     break;                                                          \
2021   case Opcode::I64AtomicRmw32##rmwop##U:                            \
2022     CHECK_TRAP(AtomicRmw<uint32_t, uint64_t>(func<uint64_t>, &pc)); \
2023     break /* no semicolon */
2024 
2025         ATOMIC_RMW(Add, Add);
2026         ATOMIC_RMW(Sub, Sub);
2027         ATOMIC_RMW(And, IntAnd);
2028         ATOMIC_RMW(Or, IntOr);
2029         ATOMIC_RMW(Xor, IntXor);
2030         ATOMIC_RMW(Xchg, Xchg);
2031 
2032 #undef ATOMIC_RMW
2033 
2034       case Opcode::I32AtomicRmwCmpxchg:
2035         CHECK_TRAP(AtomicRmwCmpxchg<uint32_t, uint32_t>(&pc));
2036         break;
2037 
2038       case Opcode::I64AtomicRmwCmpxchg:
2039         CHECK_TRAP(AtomicRmwCmpxchg<uint64_t, uint64_t>(&pc));
2040         break;
2041 
2042       case Opcode::I32AtomicRmw8CmpxchgU:
2043         CHECK_TRAP(AtomicRmwCmpxchg<uint8_t, uint32_t>(&pc));
2044         break;
2045 
2046       case Opcode::I32AtomicRmw16CmpxchgU:
2047         CHECK_TRAP(AtomicRmwCmpxchg<uint16_t, uint32_t>(&pc));
2048         break;
2049 
2050       case Opcode::I64AtomicRmw8CmpxchgU:
2051         CHECK_TRAP(AtomicRmwCmpxchg<uint8_t, uint64_t>(&pc));
2052         break;
2053 
2054       case Opcode::I64AtomicRmw16CmpxchgU:
2055         CHECK_TRAP(AtomicRmwCmpxchg<uint16_t, uint64_t>(&pc));
2056         break;
2057 
2058       case Opcode::I64AtomicRmw32CmpxchgU:
2059         CHECK_TRAP(AtomicRmwCmpxchg<uint32_t, uint64_t>(&pc));
2060         break;
2061 
2062       case Opcode::MemorySize:
2063         CHECK_TRAP(Push<uint32_t>(ReadMemory(&pc)->page_limits.initial));
2064         break;
2065 
2066       case Opcode::MemoryGrow: {
2067         Memory* memory = ReadMemory(&pc);
2068         uint32_t old_page_size = memory->page_limits.initial;
2069         uint32_t grow_pages = Pop<uint32_t>();
2070         uint32_t new_page_size = old_page_size + grow_pages;
2071         uint32_t max_page_size = memory->page_limits.has_max
2072                                      ? memory->page_limits.max
2073                                      : WABT_MAX_PAGES;
2074         PUSH_NEG_1_AND_BREAK_IF(new_page_size > max_page_size);
2075         PUSH_NEG_1_AND_BREAK_IF(
2076             static_cast<uint64_t>(new_page_size) * WABT_PAGE_SIZE > UINT32_MAX);
2077         memory->data.resize(new_page_size * WABT_PAGE_SIZE);
2078         memory->page_limits.initial = new_page_size;
2079         CHECK_TRAP(Push<uint32_t>(old_page_size));
2080         break;
2081       }
2082 
2083       case Opcode::I32Add:
2084         CHECK_TRAP(Binop(Add<uint32_t>));
2085         break;
2086 
2087       case Opcode::I32Sub:
2088         CHECK_TRAP(Binop(Sub<uint32_t>));
2089         break;
2090 
2091       case Opcode::I32Mul:
2092         CHECK_TRAP(Binop(Mul<uint32_t>));
2093         break;
2094 
2095       case Opcode::I32DivS:
2096         CHECK_TRAP(BinopTrap(IntDivS<int32_t>));
2097         break;
2098 
2099       case Opcode::I32DivU:
2100         CHECK_TRAP(BinopTrap(IntDivU<uint32_t>));
2101         break;
2102 
2103       case Opcode::I32RemS:
2104         CHECK_TRAP(BinopTrap(IntRemS<int32_t>));
2105         break;
2106 
2107       case Opcode::I32RemU:
2108         CHECK_TRAP(BinopTrap(IntRemU<uint32_t>));
2109         break;
2110 
2111       case Opcode::I32And:
2112         CHECK_TRAP(Binop(IntAnd<uint32_t>));
2113         break;
2114 
2115       case Opcode::I32Or:
2116         CHECK_TRAP(Binop(IntOr<uint32_t>));
2117         break;
2118 
2119       case Opcode::I32Xor:
2120         CHECK_TRAP(Binop(IntXor<uint32_t>));
2121         break;
2122 
2123       case Opcode::I32Shl:
2124         CHECK_TRAP(Binop(IntShl<uint32_t>));
2125         break;
2126 
2127       case Opcode::I32ShrU:
2128         CHECK_TRAP(Binop(IntShr<uint32_t>));
2129         break;
2130 
2131       case Opcode::I32ShrS:
2132         CHECK_TRAP(Binop(IntShr<int32_t>));
2133         break;
2134 
2135       case Opcode::I32Eq:
2136         CHECK_TRAP(Binop(Eq<uint32_t>));
2137         break;
2138 
2139       case Opcode::I32Ne:
2140         CHECK_TRAP(Binop(Ne<uint32_t>));
2141         break;
2142 
2143       case Opcode::I32LtS:
2144         CHECK_TRAP(Binop(Lt<int32_t>));
2145         break;
2146 
2147       case Opcode::I32LeS:
2148         CHECK_TRAP(Binop(Le<int32_t>));
2149         break;
2150 
2151       case Opcode::I32LtU:
2152         CHECK_TRAP(Binop(Lt<uint32_t>));
2153         break;
2154 
2155       case Opcode::I32LeU:
2156         CHECK_TRAP(Binop(Le<uint32_t>));
2157         break;
2158 
2159       case Opcode::I32GtS:
2160         CHECK_TRAP(Binop(Gt<int32_t>));
2161         break;
2162 
2163       case Opcode::I32GeS:
2164         CHECK_TRAP(Binop(Ge<int32_t>));
2165         break;
2166 
2167       case Opcode::I32GtU:
2168         CHECK_TRAP(Binop(Gt<uint32_t>));
2169         break;
2170 
2171       case Opcode::I32GeU:
2172         CHECK_TRAP(Binop(Ge<uint32_t>));
2173         break;
2174 
2175       case Opcode::I32Clz:
2176         CHECK_TRAP(Push<uint32_t>(Clz(Pop<uint32_t>())));
2177         break;
2178 
2179       case Opcode::I32Ctz:
2180         CHECK_TRAP(Push<uint32_t>(Ctz(Pop<uint32_t>())));
2181         break;
2182 
2183       case Opcode::I32Popcnt:
2184         CHECK_TRAP(Push<uint32_t>(Popcount(Pop<uint32_t>())));
2185         break;
2186 
2187       case Opcode::I32Eqz:
2188         CHECK_TRAP(Unop(IntEqz<uint32_t, uint32_t>));
2189         break;
2190 
2191       case Opcode::I64Add:
2192         CHECK_TRAP(Binop(Add<uint64_t>));
2193         break;
2194 
2195       case Opcode::I64Sub:
2196         CHECK_TRAP(Binop(Sub<uint64_t>));
2197         break;
2198 
2199       case Opcode::I64Mul:
2200         CHECK_TRAP(Binop(Mul<uint64_t>));
2201         break;
2202 
2203       case Opcode::I64DivS:
2204         CHECK_TRAP(BinopTrap(IntDivS<int64_t>));
2205         break;
2206 
2207       case Opcode::I64DivU:
2208         CHECK_TRAP(BinopTrap(IntDivU<uint64_t>));
2209         break;
2210 
2211       case Opcode::I64RemS:
2212         CHECK_TRAP(BinopTrap(IntRemS<int64_t>));
2213         break;
2214 
2215       case Opcode::I64RemU:
2216         CHECK_TRAP(BinopTrap(IntRemU<uint64_t>));
2217         break;
2218 
2219       case Opcode::I64And:
2220         CHECK_TRAP(Binop(IntAnd<uint64_t>));
2221         break;
2222 
2223       case Opcode::I64Or:
2224         CHECK_TRAP(Binop(IntOr<uint64_t>));
2225         break;
2226 
2227       case Opcode::I64Xor:
2228         CHECK_TRAP(Binop(IntXor<uint64_t>));
2229         break;
2230 
2231       case Opcode::I64Shl:
2232         CHECK_TRAP(Binop(IntShl<uint64_t>));
2233         break;
2234 
2235       case Opcode::I64ShrU:
2236         CHECK_TRAP(Binop(IntShr<uint64_t>));
2237         break;
2238 
2239       case Opcode::I64ShrS:
2240         CHECK_TRAP(Binop(IntShr<int64_t>));
2241         break;
2242 
2243       case Opcode::I64Eq:
2244         CHECK_TRAP(Binop(Eq<uint64_t>));
2245         break;
2246 
2247       case Opcode::I64Ne:
2248         CHECK_TRAP(Binop(Ne<uint64_t>));
2249         break;
2250 
2251       case Opcode::I64LtS:
2252         CHECK_TRAP(Binop(Lt<int64_t>));
2253         break;
2254 
2255       case Opcode::I64LeS:
2256         CHECK_TRAP(Binop(Le<int64_t>));
2257         break;
2258 
2259       case Opcode::I64LtU:
2260         CHECK_TRAP(Binop(Lt<uint64_t>));
2261         break;
2262 
2263       case Opcode::I64LeU:
2264         CHECK_TRAP(Binop(Le<uint64_t>));
2265         break;
2266 
2267       case Opcode::I64GtS:
2268         CHECK_TRAP(Binop(Gt<int64_t>));
2269         break;
2270 
2271       case Opcode::I64GeS:
2272         CHECK_TRAP(Binop(Ge<int64_t>));
2273         break;
2274 
2275       case Opcode::I64GtU:
2276         CHECK_TRAP(Binop(Gt<uint64_t>));
2277         break;
2278 
2279       case Opcode::I64GeU:
2280         CHECK_TRAP(Binop(Ge<uint64_t>));
2281         break;
2282 
2283       case Opcode::I64Clz:
2284         CHECK_TRAP(Push<uint64_t>(Clz(Pop<uint64_t>())));
2285         break;
2286 
2287       case Opcode::I64Ctz:
2288         CHECK_TRAP(Push<uint64_t>(Ctz(Pop<uint64_t>())));
2289         break;
2290 
2291       case Opcode::I64Popcnt:
2292         CHECK_TRAP(Push<uint64_t>(Popcount(Pop<uint64_t>())));
2293         break;
2294 
2295       case Opcode::F32Add:
2296         CHECK_TRAP(Binop(Add<float>));
2297         break;
2298 
2299       case Opcode::F32Sub:
2300         CHECK_TRAP(Binop(Sub<float>));
2301         break;
2302 
2303       case Opcode::F32Mul:
2304         CHECK_TRAP(Binop(Mul<float>));
2305         break;
2306 
2307       case Opcode::F32Div:
2308         CHECK_TRAP(Binop(FloatDiv<float>));
2309         break;
2310 
2311       case Opcode::F32Min:
2312         CHECK_TRAP(Binop(FloatMin<float>));
2313         break;
2314 
2315       case Opcode::F32Max:
2316         CHECK_TRAP(Binop(FloatMax<float>));
2317         break;
2318 
2319       case Opcode::F32Abs:
2320         CHECK_TRAP(Unop(FloatAbs<float>));
2321         break;
2322 
2323       case Opcode::F32Neg:
2324         CHECK_TRAP(Unop(FloatNeg<float>));
2325         break;
2326 
2327       case Opcode::F32Copysign:
2328         CHECK_TRAP(Binop(FloatCopySign<float>));
2329         break;
2330 
2331       case Opcode::F32Ceil:
2332         CHECK_TRAP(Unop(FloatCeil<float>));
2333         break;
2334 
2335       case Opcode::F32Floor:
2336         CHECK_TRAP(Unop(FloatFloor<float>));
2337         break;
2338 
2339       case Opcode::F32Trunc:
2340         CHECK_TRAP(Unop(FloatTrunc<float>));
2341         break;
2342 
2343       case Opcode::F32Nearest:
2344         CHECK_TRAP(Unop(FloatNearest<float>));
2345         break;
2346 
2347       case Opcode::F32Sqrt:
2348         CHECK_TRAP(Unop(FloatSqrt<float>));
2349         break;
2350 
2351       case Opcode::F32Eq:
2352         CHECK_TRAP(Binop(Eq<float>));
2353         break;
2354 
2355       case Opcode::F32Ne:
2356         CHECK_TRAP(Binop(Ne<float>));
2357         break;
2358 
2359       case Opcode::F32Lt:
2360         CHECK_TRAP(Binop(Lt<float>));
2361         break;
2362 
2363       case Opcode::F32Le:
2364         CHECK_TRAP(Binop(Le<float>));
2365         break;
2366 
2367       case Opcode::F32Gt:
2368         CHECK_TRAP(Binop(Gt<float>));
2369         break;
2370 
2371       case Opcode::F32Ge:
2372         CHECK_TRAP(Binop(Ge<float>));
2373         break;
2374 
2375       case Opcode::F64Add:
2376         CHECK_TRAP(Binop(Add<double>));
2377         break;
2378 
2379       case Opcode::F64Sub:
2380         CHECK_TRAP(Binop(Sub<double>));
2381         break;
2382 
2383       case Opcode::F64Mul:
2384         CHECK_TRAP(Binop(Mul<double>));
2385         break;
2386 
2387       case Opcode::F64Div:
2388         CHECK_TRAP(Binop(FloatDiv<double>));
2389         break;
2390 
2391       case Opcode::F64Min:
2392         CHECK_TRAP(Binop(FloatMin<double>));
2393         break;
2394 
2395       case Opcode::F64Max:
2396         CHECK_TRAP(Binop(FloatMax<double>));
2397         break;
2398 
2399       case Opcode::F64Abs:
2400         CHECK_TRAP(Unop(FloatAbs<double>));
2401         break;
2402 
2403       case Opcode::F64Neg:
2404         CHECK_TRAP(Unop(FloatNeg<double>));
2405         break;
2406 
2407       case Opcode::F64Copysign:
2408         CHECK_TRAP(Binop(FloatCopySign<double>));
2409         break;
2410 
2411       case Opcode::F64Ceil:
2412         CHECK_TRAP(Unop(FloatCeil<double>));
2413         break;
2414 
2415       case Opcode::F64Floor:
2416         CHECK_TRAP(Unop(FloatFloor<double>));
2417         break;
2418 
2419       case Opcode::F64Trunc:
2420         CHECK_TRAP(Unop(FloatTrunc<double>));
2421         break;
2422 
2423       case Opcode::F64Nearest:
2424         CHECK_TRAP(Unop(FloatNearest<double>));
2425         break;
2426 
2427       case Opcode::F64Sqrt:
2428         CHECK_TRAP(Unop(FloatSqrt<double>));
2429         break;
2430 
2431       case Opcode::F64Eq:
2432         CHECK_TRAP(Binop(Eq<double>));
2433         break;
2434 
2435       case Opcode::F64Ne:
2436         CHECK_TRAP(Binop(Ne<double>));
2437         break;
2438 
2439       case Opcode::F64Lt:
2440         CHECK_TRAP(Binop(Lt<double>));
2441         break;
2442 
2443       case Opcode::F64Le:
2444         CHECK_TRAP(Binop(Le<double>));
2445         break;
2446 
2447       case Opcode::F64Gt:
2448         CHECK_TRAP(Binop(Gt<double>));
2449         break;
2450 
2451       case Opcode::F64Ge:
2452         CHECK_TRAP(Binop(Ge<double>));
2453         break;
2454 
2455       case Opcode::I32TruncF32S:
2456         CHECK_TRAP(UnopTrap(IntTrunc<int32_t, float>));
2457         break;
2458 
2459       case Opcode::I32TruncSatF32S:
2460         CHECK_TRAP(Unop(IntTruncSat<int32_t, float>));
2461         break;
2462 
2463       case Opcode::I32TruncF64S:
2464         CHECK_TRAP(UnopTrap(IntTrunc<int32_t, double>));
2465         break;
2466 
2467       case Opcode::I32TruncSatF64S:
2468         CHECK_TRAP(Unop(IntTruncSat<int32_t, double>));
2469         break;
2470 
2471       case Opcode::I32TruncF32U:
2472         CHECK_TRAP(UnopTrap(IntTrunc<uint32_t, float>));
2473         break;
2474 
2475       case Opcode::I32TruncSatF32U:
2476         CHECK_TRAP(Unop(IntTruncSat<uint32_t, float>));
2477         break;
2478 
2479       case Opcode::I32TruncF64U:
2480         CHECK_TRAP(UnopTrap(IntTrunc<uint32_t, double>));
2481         break;
2482 
2483       case Opcode::I32TruncSatF64U:
2484         CHECK_TRAP(Unop(IntTruncSat<uint32_t, double>));
2485         break;
2486 
2487       case Opcode::I32WrapI64:
2488         CHECK_TRAP(Push<uint32_t>(Pop<uint64_t>()));
2489         break;
2490 
2491       case Opcode::I64TruncF32S:
2492         CHECK_TRAP(UnopTrap(IntTrunc<int64_t, float>));
2493         break;
2494 
2495       case Opcode::I64TruncSatF32S:
2496         CHECK_TRAP(Unop(IntTruncSat<int64_t, float>));
2497         break;
2498 
2499       case Opcode::I64TruncF64S:
2500         CHECK_TRAP(UnopTrap(IntTrunc<int64_t, double>));
2501         break;
2502 
2503       case Opcode::I64TruncSatF64S:
2504         CHECK_TRAP(Unop(IntTruncSat<int64_t, double>));
2505         break;
2506 
2507       case Opcode::I64TruncF32U:
2508         CHECK_TRAP(UnopTrap(IntTrunc<uint64_t, float>));
2509         break;
2510 
2511       case Opcode::I64TruncSatF32U:
2512         CHECK_TRAP(Unop(IntTruncSat<uint64_t, float>));
2513         break;
2514 
2515       case Opcode::I64TruncF64U:
2516         CHECK_TRAP(UnopTrap(IntTrunc<uint64_t, double>));
2517         break;
2518 
2519       case Opcode::I64TruncSatF64U:
2520         CHECK_TRAP(Unop(IntTruncSat<uint64_t, double>));
2521         break;
2522 
2523       case Opcode::I64ExtendI32S:
2524         CHECK_TRAP(Push<uint64_t>(Pop<int32_t>()));
2525         break;
2526 
2527       case Opcode::I64ExtendI32U:
2528         CHECK_TRAP(Push<uint64_t>(Pop<uint32_t>()));
2529         break;
2530 
2531       case Opcode::F32ConvertI32S:
2532         CHECK_TRAP(Push<float>(Pop<int32_t>()));
2533         break;
2534 
2535       case Opcode::F32ConvertI32U:
2536         CHECK_TRAP(Push<float>(Pop<uint32_t>()));
2537         break;
2538 
2539       case Opcode::F32ConvertI64S:
2540         CHECK_TRAP(Push<float>(wabt_convert_int64_to_float(Pop<int64_t>())));
2541         break;
2542 
2543       case Opcode::F32ConvertI64U:
2544         CHECK_TRAP(Push<float>(wabt_convert_uint64_to_float(Pop<uint64_t>())));
2545         break;
2546 
2547       case Opcode::F32DemoteF64: {
2548         typedef FloatTraits<float> F32Traits;
2549 
2550         uint64_t value = PopRep<double>();
2551         if (WABT_LIKELY((IsConversionInRange<float, double>(value)))) {
2552           CHECK_TRAP(Push<float>(FromRep<double>(value)));
2553         } else if (IsInRangeF64DemoteF32RoundToF32Max(value)) {
2554           CHECK_TRAP(PushRep<float>(F32Traits::kMax));
2555         } else if (IsInRangeF64DemoteF32RoundToNegF32Max(value)) {
2556           CHECK_TRAP(PushRep<float>(F32Traits::kNegMax));
2557         } else if (FloatTraits<double>::IsNan(value)) {
2558           CHECK_TRAP(PushRep<float>(F32Traits::kQuietNan));
2559         } else {
2560           // Infinity.
2561           uint32_t sign = (value >> 32) & F32Traits::kSignMask;
2562           CHECK_TRAP(PushRep<float>(sign | F32Traits::kInf));
2563         }
2564         break;
2565       }
2566 
2567       case Opcode::F32ReinterpretI32:
2568         CHECK_TRAP(PushRep<float>(Pop<uint32_t>()));
2569         break;
2570 
2571       case Opcode::F64ConvertI32S:
2572         CHECK_TRAP(Push<double>(Pop<int32_t>()));
2573         break;
2574 
2575       case Opcode::F64ConvertI32U:
2576         CHECK_TRAP(Push<double>(Pop<uint32_t>()));
2577         break;
2578 
2579       case Opcode::F64ConvertI64S:
2580         CHECK_TRAP(Push<double>(wabt_convert_int64_to_double(Pop<int64_t>())));
2581         break;
2582 
2583       case Opcode::F64ConvertI64U:
2584         CHECK_TRAP(
2585             Push<double>(wabt_convert_uint64_to_double(Pop<uint64_t>())));
2586         break;
2587 
2588       case Opcode::F64PromoteF32: {
2589         uint32_t value = PopRep<float>();
2590         if (WABT_UNLIKELY(FloatTraits<float>::IsNan(value))) {
2591           CHECK_TRAP(PushRep<double>(FloatTraits<double>::kQuietNan));
2592         } else {
2593           CHECK_TRAP(Push<double>(Bitcast<float>(value)));
2594         }
2595         break;
2596       }
2597 
2598       case Opcode::F64ReinterpretI64:
2599         CHECK_TRAP(PushRep<double>(Pop<uint64_t>()));
2600         break;
2601 
2602       case Opcode::I32ReinterpretF32:
2603         CHECK_TRAP(Push<uint32_t>(PopRep<float>()));
2604         break;
2605 
2606       case Opcode::I64ReinterpretF64:
2607         CHECK_TRAP(Push<uint64_t>(PopRep<double>()));
2608         break;
2609 
2610       case Opcode::I32Rotr:
2611         CHECK_TRAP(Binop(IntRotr<uint32_t>));
2612         break;
2613 
2614       case Opcode::I32Rotl:
2615         CHECK_TRAP(Binop(IntRotl<uint32_t>));
2616         break;
2617 
2618       case Opcode::I64Rotr:
2619         CHECK_TRAP(Binop(IntRotr<uint64_t>));
2620         break;
2621 
2622       case Opcode::I64Rotl:
2623         CHECK_TRAP(Binop(IntRotl<uint64_t>));
2624         break;
2625 
2626       case Opcode::I64Eqz:
2627         CHECK_TRAP(Unop(IntEqz<uint32_t, uint64_t>));
2628         break;
2629 
2630       case Opcode::I32Extend8S:
2631         CHECK_TRAP(Unop(IntExtendS<uint32_t, int8_t>));
2632         break;
2633 
2634       case Opcode::I32Extend16S:
2635         CHECK_TRAP(Unop(IntExtendS<uint32_t, int16_t>));
2636         break;
2637 
2638       case Opcode::I64Extend8S:
2639         CHECK_TRAP(Unop(IntExtendS<uint64_t, int8_t>));
2640         break;
2641 
2642       case Opcode::I64Extend16S:
2643         CHECK_TRAP(Unop(IntExtendS<uint64_t, int16_t>));
2644         break;
2645 
2646       case Opcode::I64Extend32S:
2647         CHECK_TRAP(Unop(IntExtendS<uint64_t, int32_t>));
2648         break;
2649 
2650       case Opcode::InterpAlloca: {
2651         uint32_t old_value_stack_top = value_stack_top_;
2652         size_t count = ReadU32(&pc);
2653         value_stack_top_ += count;
2654         CHECK_STACK();
2655         memset(&value_stack_[old_value_stack_top], 0, count * sizeof(Value));
2656         break;
2657       }
2658 
2659       case Opcode::InterpBrUnless: {
2660         IstreamOffset new_pc = ReadU32(&pc);
2661         if (!Pop<uint32_t>()) {
2662           GOTO(new_pc);
2663         }
2664         break;
2665       }
2666 
2667       case Opcode::Drop:
2668         (void)Pop();
2669         break;
2670 
2671       case Opcode::InterpDropKeep: {
2672         uint32_t drop_count = ReadU32(&pc);
2673         uint32_t keep_count = ReadU32(&pc);
2674         DropKeep(drop_count, keep_count);
2675         break;
2676       }
2677 
2678       case Opcode::Nop:
2679         break;
2680 
2681       case Opcode::I32AtomicWait:
2682       case Opcode::I64AtomicWait:
2683       case Opcode::AtomicNotify:
2684         // TODO(binji): Implement.
2685         TRAP(Unreachable);
2686         break;
2687 
2688       case Opcode::V128Const: {
2689         CHECK_TRAP(PushRep<v128>(ReadV128(&pc)));
2690         break;
2691       }
2692 
2693       case Opcode::V128Load:
2694         CHECK_TRAP(Load<v128>(&pc));
2695         break;
2696 
2697       case Opcode::V128Store:
2698         CHECK_TRAP(Store<v128>(&pc));
2699         break;
2700 
2701       case Opcode::I8X16Splat: {
2702         uint8_t lane_data = Pop<uint32_t>();
2703         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint8_t>(lane_data)));
2704         break;
2705       }
2706 
2707       case Opcode::I16X8Splat: {
2708         uint16_t lane_data = Pop<uint32_t>();
2709         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint16_t>(lane_data)));
2710         break;
2711       }
2712 
2713       case Opcode::I32X4Splat: {
2714         uint32_t lane_data = Pop<uint32_t>();
2715         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint32_t>(lane_data)));
2716         break;
2717       }
2718 
2719       case Opcode::I64X2Splat: {
2720         uint64_t lane_data = Pop<uint64_t>();
2721         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint64_t>(lane_data)));
2722         break;
2723       }
2724 
2725       case Opcode::F32X4Splat: {
2726         float lane_data = Pop<float>();
2727         CHECK_TRAP(Push<v128>(SimdSplat<v128, float>(lane_data)));
2728         break;
2729       }
2730 
2731       case Opcode::F64X2Splat: {
2732         double lane_data = Pop<double>();
2733         CHECK_TRAP(Push<v128>(SimdSplat<v128, double>(lane_data)));
2734         break;
2735       }
2736 
2737       case Opcode::I8X16ExtractLaneS: {
2738         v128 lane_val = static_cast<v128>(Pop<v128>());
2739         uint32_t lane_idx = ReadU8(&pc);
2740         CHECK_TRAP(PushRep<int32_t>(
2741             SimdExtractLane<int32_t, v128, int8_t>(lane_val, lane_idx)));
2742         break;
2743       }
2744 
2745       case Opcode::I8X16ExtractLaneU: {
2746         v128 lane_val = static_cast<v128>(Pop<v128>());
2747         uint32_t lane_idx = ReadU8(&pc);
2748         CHECK_TRAP(PushRep<int32_t>(
2749             SimdExtractLane<int32_t, v128, uint8_t>(lane_val, lane_idx)));
2750         break;
2751       }
2752 
2753       case Opcode::I16X8ExtractLaneS: {
2754         v128 lane_val = static_cast<v128>(Pop<v128>());
2755         uint32_t lane_idx = ReadU8(&pc);
2756         CHECK_TRAP(PushRep<int32_t>(
2757             SimdExtractLane<int32_t, v128, int16_t>(lane_val, lane_idx)));
2758         break;
2759       }
2760 
2761       case Opcode::I16X8ExtractLaneU: {
2762         v128 lane_val = static_cast<v128>(Pop<v128>());
2763         uint32_t lane_idx = ReadU8(&pc);
2764         CHECK_TRAP(PushRep<int32_t>(
2765             SimdExtractLane<int32_t, v128, uint16_t>(lane_val, lane_idx)));
2766         break;
2767       }
2768 
2769       case Opcode::I32X4ExtractLane: {
2770         v128 lane_val = static_cast<v128>(Pop<v128>());
2771         uint32_t lane_idx = ReadU8(&pc);
2772         CHECK_TRAP(PushRep<int32_t>(
2773             SimdExtractLane<int32_t, v128, int32_t>(lane_val, lane_idx)));
2774         break;
2775       }
2776 
2777       case Opcode::I64X2ExtractLane: {
2778         v128 lane_val = static_cast<v128>(Pop<v128>());
2779         uint32_t lane_idx = ReadU8(&pc);
2780         CHECK_TRAP(PushRep<int64_t>(
2781             SimdExtractLane<int64_t, v128, int64_t>(lane_val, lane_idx)));
2782         break;
2783       }
2784 
2785       case Opcode::F32X4ExtractLane: {
2786         v128 lane_val = static_cast<v128>(Pop<v128>());
2787         uint32_t lane_idx = ReadU8(&pc);
2788         CHECK_TRAP(PushRep<float>(
2789             SimdExtractLane<int32_t, v128, int32_t>(lane_val, lane_idx)));
2790         break;
2791       }
2792 
2793       case Opcode::F64X2ExtractLane: {
2794         v128 lane_val = static_cast<v128>(Pop<v128>());
2795         uint32_t lane_idx = ReadU8(&pc);
2796         CHECK_TRAP(PushRep<double>(
2797             SimdExtractLane<int64_t, v128, int64_t>(lane_val, lane_idx)));
2798         break;
2799       }
2800 
2801       case Opcode::I8X16ReplaceLane: {
2802         int8_t lane_val = static_cast<int8_t>(Pop<int32_t>());
2803         v128 value = static_cast<v128>(Pop<v128>());
2804         uint32_t lane_idx = ReadU8(&pc);
2805         CHECK_TRAP(Push<v128>(
2806             SimdReplaceLane<v128, v128, int8_t>(value, lane_idx, lane_val)));
2807         break;
2808       }
2809 
2810       case Opcode::I16X8ReplaceLane: {
2811         int16_t lane_val = static_cast<int16_t>(Pop<int32_t>());
2812         v128 value = static_cast<v128>(Pop<v128>());
2813         uint32_t lane_idx = ReadU8(&pc);
2814         CHECK_TRAP(Push<v128>(
2815             SimdReplaceLane<v128, v128, int16_t>(value, lane_idx, lane_val)));
2816         break;
2817       }
2818 
2819       case Opcode::I32X4ReplaceLane: {
2820         int32_t lane_val = Pop<int32_t>();
2821         v128 value = static_cast<v128>(Pop<v128>());
2822         uint32_t lane_idx = ReadU8(&pc);
2823         CHECK_TRAP(Push<v128>(
2824             SimdReplaceLane<v128, v128, int32_t>(value, lane_idx, lane_val)));
2825         break;
2826       }
2827 
2828       case Opcode::I64X2ReplaceLane: {
2829         int64_t lane_val = Pop<int64_t>();
2830         v128 value = static_cast<v128>(Pop<v128>());
2831         uint32_t lane_idx = ReadU8(&pc);
2832         CHECK_TRAP(Push<v128>(
2833             SimdReplaceLane<v128, v128, int64_t>(value, lane_idx, lane_val)));
2834         break;
2835       }
2836 
2837       case Opcode::F32X4ReplaceLane: {
2838         float lane_val = Pop<float>();
2839         v128 value = static_cast<v128>(Pop<v128>());
2840         uint32_t lane_idx = ReadU8(&pc);
2841         CHECK_TRAP(Push<v128>(
2842             SimdReplaceLane<v128, v128, float>(value, lane_idx, lane_val)));
2843         break;
2844       }
2845 
2846       case Opcode::F64X2ReplaceLane: {
2847         double lane_val = Pop<double>();
2848         v128 value = static_cast<v128>(Pop<v128>());
2849         uint32_t lane_idx = ReadU8(&pc);
2850         CHECK_TRAP(Push<v128>(
2851             SimdReplaceLane<v128, v128, double>(value, lane_idx, lane_val)));
2852         break;
2853       }
2854 
2855       case Opcode::V8X16Swizzle: {
2856         const int32_t lanes = 16;
2857         // Define SIMD data array for SIMD add by lanes.
2858         int8_t simd_data_ret[lanes];
2859         int8_t simd_data[lanes];
2860         int8_t simd_swizzle[lanes];
2861 
2862         v128 v2 = PopRep<v128>();
2863         v128 v1 = PopRep<v128>();
2864 
2865         // Convert input SIMD data to array.
2866         memcpy(simd_data, &v1, sizeof(v128));
2867         memcpy(simd_swizzle, &v2, sizeof(v128));
2868 
2869         // Construct the SIMD value by lane data and lane nums.
2870         for (int32_t i = 0; i < lanes; i++) {
2871           uint8_t lane_idx = simd_swizzle[i];
2872           simd_data_ret[i] = lane_idx < lanes ? simd_data[lane_idx] : 0;
2873         }
2874 
2875         CHECK_TRAP(PushRep<v128>(Bitcast<v128>(simd_data_ret)));
2876         break;
2877       }
2878 
2879     case Opcode::V8X16Shuffle: {
2880         const int32_t lanes = 16;
2881         // Define SIMD data array for SIMD add by lanes.
2882         int8_t simd_data_ret[lanes];
2883         int8_t simd_data_0[lanes];
2884         int8_t simd_data_1[lanes];
2885         int8_t simd_shuffle[lanes];
2886 
2887         v128 v2 = PopRep<v128>();
2888         v128 v1 = PopRep<v128>();
2889         v128 shuffle_imm = ReadV128(&pc);
2890 
2891         // Convert input SIMD data to array.
2892         memcpy(simd_data_0, &v1, sizeof(v128));
2893         memcpy(simd_data_1, &v2, sizeof(v128));
2894         memcpy(simd_shuffle, &shuffle_imm, sizeof(v128));
2895 
2896         // Constuct the SIMD value by lane data and lane nums.
2897         for (int32_t i = 0; i < lanes; i++) {
2898           int8_t lane_idx = simd_shuffle[i];
2899           simd_data_ret[i] = (lane_idx < lanes) ? simd_data_0[lane_idx]
2900                                                 : simd_data_1[lane_idx - lanes];
2901         }
2902 
2903         CHECK_TRAP(PushRep<v128>(Bitcast<v128>(simd_data_ret)));
2904         break;
2905       }
2906 
2907       case Opcode::I8X16LoadSplat: {
2908           CHECK_TRAP(Load<uint8_t, uint32_t>(&pc));
2909           uint8_t lane_data = Pop<uint32_t>();
2910           CHECK_TRAP(Push<v128>(SimdSplat<v128, uint8_t>(lane_data)));
2911           break;
2912       }
2913 
2914       case Opcode::I16X8LoadSplat: {
2915           CHECK_TRAP(Load<uint16_t, uint32_t>(&pc));
2916           uint16_t lane_data = Pop<uint32_t>();
2917           CHECK_TRAP(Push<v128>(SimdSplat<v128, uint16_t>(lane_data)));
2918           break;
2919       }
2920 
2921       case Opcode::I32X4LoadSplat: {
2922           CHECK_TRAP(Load<uint32_t, uint32_t>(&pc));
2923           uint32_t lane_data = Pop<uint32_t>();
2924           CHECK_TRAP(Push<v128>(SimdSplat<v128, uint32_t>(lane_data)));
2925           break;
2926       }
2927 
2928       case Opcode::I64X2LoadSplat: {
2929           CHECK_TRAP(Load<uint64_t, uint64_t>(&pc));
2930           uint64_t lane_data = Pop<uint64_t>();
2931           CHECK_TRAP(Push<v128>(SimdSplat<v128, uint64_t>(lane_data)));
2932           break;
2933       }
2934 
2935       case Opcode::I8X16Add:
2936         CHECK_TRAP(SimdBinop<v128, uint8_t>(Add<uint32_t>));
2937         break;
2938 
2939       case Opcode::I16X8Add:
2940         CHECK_TRAP(SimdBinop<v128, uint16_t>(Add<uint32_t>));
2941         break;
2942 
2943       case Opcode::I32X4Add:
2944         CHECK_TRAP(SimdBinop<v128, uint32_t>(Add<uint32_t>));
2945         break;
2946 
2947       case Opcode::I64X2Add:
2948         CHECK_TRAP(SimdBinop<v128, uint64_t>(Add<uint64_t>));
2949         break;
2950 
2951       case Opcode::I8X16Sub:
2952         CHECK_TRAP(SimdBinop<v128, uint8_t>(Sub<uint32_t>));
2953         break;
2954 
2955       case Opcode::I16X8Sub:
2956         CHECK_TRAP(SimdBinop<v128, uint16_t>(Sub<uint32_t>));
2957         break;
2958 
2959       case Opcode::I32X4Sub:
2960         CHECK_TRAP(SimdBinop<v128, uint32_t>(Sub<uint32_t>));
2961         break;
2962 
2963       case Opcode::I64X2Sub:
2964         CHECK_TRAP(SimdBinop<v128, uint64_t>(Sub<uint64_t>));
2965         break;
2966 
2967       case Opcode::I8X16Mul:
2968         CHECK_TRAP(SimdBinop<v128, uint8_t>(Mul<uint32_t>));
2969         break;
2970 
2971       case Opcode::I16X8Mul:
2972         CHECK_TRAP(SimdBinop<v128, uint16_t>(Mul<uint32_t>));
2973         break;
2974 
2975       case Opcode::I32X4Mul:
2976         CHECK_TRAP(SimdBinop<v128, uint32_t>(Mul<uint32_t>));
2977         break;
2978 
2979       case Opcode::I8X16Neg:
2980         CHECK_TRAP(SimdUnop<v128, int8_t>(IntNeg<int32_t>));
2981         break;
2982 
2983       case Opcode::I16X8Neg:
2984         CHECK_TRAP(SimdUnop<v128, int16_t>(IntNeg<int32_t>));
2985         break;
2986 
2987       case Opcode::I32X4Neg:
2988         CHECK_TRAP(SimdUnop<v128, int32_t>(IntNeg<int32_t>));
2989         break;
2990 
2991       case Opcode::I64X2Neg:
2992         CHECK_TRAP(SimdUnop<v128, int64_t>(IntNeg<int64_t>));
2993         break;
2994 
2995       case Opcode::I8X16AddSaturateS:
2996         CHECK_TRAP(SimdBinop<v128, int8_t>(AddSaturate<int32_t, int8_t>));
2997         break;
2998 
2999       case Opcode::I8X16AddSaturateU:
3000         CHECK_TRAP(SimdBinop<v128, uint8_t>(AddSaturate<uint32_t, uint8_t>));
3001         break;
3002 
3003       case Opcode::I16X8AddSaturateS:
3004         CHECK_TRAP(SimdBinop<v128, int16_t>(AddSaturate<int32_t, int16_t>));
3005         break;
3006 
3007       case Opcode::I16X8AddSaturateU:
3008         CHECK_TRAP(SimdBinop<v128, uint16_t>(AddSaturate<uint32_t, uint16_t>));
3009         break;
3010 
3011       case Opcode::I8X16SubSaturateS:
3012         CHECK_TRAP(SimdBinop<v128, int8_t>(SubSaturate<int32_t, int8_t>));
3013         break;
3014 
3015       case Opcode::I8X16SubSaturateU:
3016         CHECK_TRAP(SimdBinop<v128, uint8_t>(SubSaturate<int32_t, uint8_t>));
3017         break;
3018 
3019       case Opcode::I16X8SubSaturateS:
3020         CHECK_TRAP(SimdBinop<v128, int16_t>(SubSaturate<int32_t, int16_t>));
3021         break;
3022 
3023       case Opcode::I16X8SubSaturateU:
3024         CHECK_TRAP(SimdBinop<v128, uint16_t>(SubSaturate<int32_t, uint16_t>));
3025         break;
3026 
3027       case Opcode::I8X16Shl: {
3028         uint32_t shift_count = Pop<uint32_t>();
3029         shift_count = shift_count % 8;
3030         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint8_t>(shift_count)));
3031         CHECK_TRAP(SimdBinop<v128, uint8_t>(IntShl<uint32_t>));
3032         break;
3033       }
3034 
3035       case Opcode::I16X8Shl: {
3036         uint32_t shift_count = Pop<uint32_t>();
3037         shift_count = shift_count % 16;
3038         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint16_t>(shift_count)));
3039         CHECK_TRAP(SimdBinop<v128, uint16_t>(IntShl<uint32_t>));
3040         break;
3041       }
3042 
3043       case Opcode::I32X4Shl: {
3044         uint32_t shift_count = Pop<uint32_t>();
3045         shift_count = shift_count % 32;
3046         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint32_t>(shift_count)));
3047         CHECK_TRAP(SimdBinop<v128, uint32_t>(IntShl<uint32_t>));
3048         break;
3049       }
3050 
3051       case Opcode::I64X2Shl: {
3052         uint32_t shift_count = Pop<uint32_t>();
3053         shift_count = shift_count % 64;
3054         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint64_t>(shift_count)));
3055         CHECK_TRAP(SimdBinop<v128, uint64_t>(IntShl<uint64_t>));
3056         break;
3057       }
3058 
3059       case Opcode::I8X16ShrS: {
3060         uint32_t shift_count = Pop<uint32_t>();
3061         shift_count = shift_count % 8;
3062         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint8_t>(shift_count)));
3063         CHECK_TRAP(SimdBinop<v128, int8_t>(IntShr<int32_t>));
3064         break;
3065       }
3066 
3067       case Opcode::I8X16ShrU: {
3068         uint32_t shift_count = Pop<uint32_t>();
3069         shift_count = shift_count % 8;
3070         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint8_t>(shift_count)));
3071         CHECK_TRAP(SimdBinop<v128, uint8_t>(IntShr<uint32_t>));
3072         break;
3073       }
3074 
3075       case Opcode::I16X8ShrS: {
3076         uint32_t shift_count = Pop<uint32_t>();
3077         shift_count = shift_count % 16;
3078         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint16_t>(shift_count)));
3079         CHECK_TRAP(SimdBinop<v128, int16_t>(IntShr<int32_t>));
3080         break;
3081       }
3082 
3083       case Opcode::I16X8ShrU: {
3084         uint32_t shift_count = Pop<uint32_t>();
3085         shift_count = shift_count % 16;
3086         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint16_t>(shift_count)));
3087         CHECK_TRAP(SimdBinop<v128, uint16_t>(IntShr<uint32_t>));
3088         break;
3089       }
3090 
3091       case Opcode::I32X4ShrS: {
3092         uint32_t shift_count = Pop<uint32_t>();
3093         shift_count = shift_count % 32;
3094         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint32_t>(shift_count)));
3095         CHECK_TRAP(SimdBinop<v128, int32_t>(IntShr<int32_t>));
3096         break;
3097       }
3098 
3099       case Opcode::I32X4ShrU: {
3100         uint32_t shift_count = Pop<uint32_t>();
3101         shift_count = shift_count % 32;
3102         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint32_t>(shift_count)));
3103         CHECK_TRAP(SimdBinop<v128, uint32_t>(IntShr<uint32_t>));
3104         break;
3105       }
3106 
3107       case Opcode::I64X2ShrS: {
3108         uint32_t shift_count = Pop<uint32_t>();
3109         shift_count = shift_count % 64;
3110         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint64_t>(shift_count)));
3111         CHECK_TRAP(SimdBinop<v128, int64_t>(IntShr<int64_t>));
3112         break;
3113       }
3114 
3115       case Opcode::I64X2ShrU: {
3116         uint32_t shift_count = Pop<uint32_t>();
3117         shift_count = shift_count % 64;
3118         CHECK_TRAP(Push<v128>(SimdSplat<v128, uint64_t>(shift_count)));
3119         CHECK_TRAP(SimdBinop<v128, uint64_t>(IntShr<uint64_t>));
3120         break;
3121       }
3122 
3123       case Opcode::V128And:
3124         CHECK_TRAP(SimdBinop<v128, uint64_t>(IntAnd<uint64_t>));
3125         break;
3126 
3127       case Opcode::V128Or:
3128         CHECK_TRAP(SimdBinop<v128, uint64_t>(IntOr<uint64_t>));
3129         break;
3130 
3131       case Opcode::V128Xor:
3132         CHECK_TRAP(SimdBinop<v128, uint64_t>(IntXor<uint64_t>));
3133         break;
3134 
3135       case Opcode::V128Not:
3136         CHECK_TRAP(SimdUnop<v128, uint64_t>(IntNot<uint64_t>));
3137         break;
3138 
3139       case Opcode::V128BitSelect: {
3140         // Follow Wasm Simd spec to compute V128BitSelect:
3141         // v128.or(v128.and(v1, c), v128.and(v2, v128.not(c)))
3142         v128 c_mask = PopRep<v128>();
3143         v128 v2 = PopRep<v128>();
3144         v128 v1 = PopRep<v128>();
3145         // 1. v128.and(v1, c)
3146         CHECK_TRAP(Push<v128>(v1));
3147         CHECK_TRAP(Push<v128>(c_mask));
3148         CHECK_TRAP(SimdBinop<v128, uint64_t>(IntAnd<uint64_t>));
3149         // 2. v128.and(v2, v128.not(c))
3150         CHECK_TRAP(Push<v128>(v2));
3151         CHECK_TRAP(Push<v128>(c_mask));
3152         CHECK_TRAP(SimdUnop<v128, uint64_t>(IntNot<uint64_t>));
3153         CHECK_TRAP(SimdBinop<v128, uint64_t>(IntAnd<uint64_t>));
3154         // 3. v128.or( 1 , 2)
3155         CHECK_TRAP(SimdBinop<v128, uint64_t>(IntOr<uint64_t>));
3156         break;
3157       }
3158 
3159       case Opcode::I8X16AnyTrue: {
3160         v128 value = PopRep<v128>();
3161         CHECK_TRAP(Push<int32_t>(SimdIsLaneTrue<v128, uint8_t>(value, 1)));
3162         break;
3163       }
3164 
3165       case Opcode::I16X8AnyTrue: {
3166         v128 value = PopRep<v128>();
3167         CHECK_TRAP(Push<int32_t>(SimdIsLaneTrue<v128, uint16_t>(value, 1)));
3168         break;
3169       }
3170 
3171       case Opcode::I32X4AnyTrue: {
3172         v128 value = PopRep<v128>();
3173         CHECK_TRAP(Push<int32_t>(SimdIsLaneTrue<v128, uint32_t>(value, 1)));
3174         break;
3175       }
3176 
3177       case Opcode::I64X2AnyTrue: {
3178         v128 value = PopRep<v128>();
3179         CHECK_TRAP(Push<int32_t>(SimdIsLaneTrue<v128, uint64_t>(value, 1)));
3180         break;
3181       }
3182 
3183       case Opcode::I8X16AllTrue: {
3184         v128 value = PopRep<v128>();
3185         CHECK_TRAP(Push<int32_t>(SimdIsLaneTrue<v128, uint8_t>(value, 16)));
3186         break;
3187       }
3188 
3189       case Opcode::I16X8AllTrue: {
3190         v128 value = PopRep<v128>();
3191         CHECK_TRAP(Push<int32_t>(SimdIsLaneTrue<v128, uint16_t>(value, 8)));
3192         break;
3193       }
3194 
3195       case Opcode::I32X4AllTrue: {
3196         v128 value = PopRep<v128>();
3197         CHECK_TRAP(Push<int32_t>(SimdIsLaneTrue<v128, uint32_t>(value, 4)));
3198         break;
3199       }
3200 
3201       case Opcode::I64X2AllTrue: {
3202         v128 value = PopRep<v128>();
3203         CHECK_TRAP(Push<int32_t>(SimdIsLaneTrue<v128, uint64_t>(value, 2)));
3204         break;
3205       }
3206 
3207       case Opcode::I8X16Eq:
3208         CHECK_TRAP(SimdRelBinop<v128, int8_t>(Eq<int32_t>));
3209         break;
3210 
3211       case Opcode::I16X8Eq:
3212         CHECK_TRAP(SimdRelBinop<v128, int16_t>(Eq<int32_t>));
3213         break;
3214 
3215       case Opcode::I32X4Eq:
3216         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Eq<int32_t>));
3217         break;
3218 
3219       case Opcode::F32X4Eq:
3220         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Eq<float>));
3221         break;
3222 
3223       case Opcode::F64X2Eq:
3224         CHECK_TRAP(SimdRelBinop<v128, int64_t>(Eq<double>));
3225         break;
3226 
3227       case Opcode::I8X16Ne:
3228         CHECK_TRAP(SimdRelBinop<v128, int8_t>(Ne<int32_t>));
3229         break;
3230 
3231       case Opcode::I16X8Ne:
3232         CHECK_TRAP(SimdRelBinop<v128, int16_t>(Ne<int32_t>));
3233         break;
3234 
3235       case Opcode::I32X4Ne:
3236         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Ne<int32_t>));
3237         break;
3238 
3239       case Opcode::F32X4Ne:
3240         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Ne<float>));
3241         break;
3242 
3243       case Opcode::F64X2Ne:
3244         CHECK_TRAP(SimdRelBinop<v128, int64_t>(Ne<double>));
3245         break;
3246 
3247       case Opcode::I8X16LtS:
3248         CHECK_TRAP(SimdRelBinop<v128, int8_t>(Lt<int32_t>));
3249         break;
3250 
3251       case Opcode::I8X16LtU:
3252         CHECK_TRAP(SimdRelBinop<v128, uint8_t>(Lt<uint32_t>));
3253         break;
3254 
3255       case Opcode::I16X8LtS:
3256         CHECK_TRAP(SimdRelBinop<v128, int16_t>(Lt<int32_t>));
3257         break;
3258 
3259       case Opcode::I16X8LtU:
3260         CHECK_TRAP(SimdRelBinop<v128, uint16_t>(Lt<uint32_t>));
3261         break;
3262 
3263       case Opcode::I32X4LtS:
3264         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Lt<int32_t>));
3265         break;
3266 
3267       case Opcode::I32X4LtU:
3268         CHECK_TRAP(SimdRelBinop<v128, uint32_t>(Lt<uint32_t>));
3269         break;
3270 
3271       case Opcode::F32X4Lt:
3272         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Lt<float>));
3273         break;
3274 
3275       case Opcode::F64X2Lt:
3276         CHECK_TRAP(SimdRelBinop<v128, int64_t>(Lt<double>));
3277         break;
3278 
3279       case Opcode::I8X16LeS:
3280         CHECK_TRAP(SimdRelBinop<v128, int8_t>(Le<int32_t>));
3281         break;
3282 
3283       case Opcode::I8X16LeU:
3284         CHECK_TRAP(SimdRelBinop<v128, uint8_t>(Le<uint32_t>));
3285         break;
3286 
3287       case Opcode::I16X8LeS:
3288         CHECK_TRAP(SimdRelBinop<v128, int16_t>(Le<int32_t>));
3289         break;
3290 
3291       case Opcode::I16X8LeU:
3292         CHECK_TRAP(SimdRelBinop<v128, uint16_t>(Le<uint32_t>));
3293         break;
3294 
3295       case Opcode::I32X4LeS:
3296         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Le<int32_t>));
3297         break;
3298 
3299       case Opcode::I32X4LeU:
3300         CHECK_TRAP(SimdRelBinop<v128, uint32_t>(Le<uint32_t>));
3301         break;
3302 
3303       case Opcode::F32X4Le:
3304         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Le<float>));
3305         break;
3306 
3307       case Opcode::F64X2Le:
3308         CHECK_TRAP(SimdRelBinop<v128, int64_t>(Le<double>));
3309         break;
3310 
3311       case Opcode::I8X16GtS:
3312         CHECK_TRAP(SimdRelBinop<v128, int8_t>(Gt<int32_t>));
3313         break;
3314 
3315       case Opcode::I8X16GtU:
3316         CHECK_TRAP(SimdRelBinop<v128, uint8_t>(Gt<uint32_t>));
3317         break;
3318 
3319       case Opcode::I16X8GtS:
3320         CHECK_TRAP(SimdRelBinop<v128, int16_t>(Gt<int32_t>));
3321         break;
3322 
3323       case Opcode::I16X8GtU:
3324         CHECK_TRAP(SimdRelBinop<v128, uint16_t>(Gt<uint32_t>));
3325         break;
3326 
3327       case Opcode::I32X4GtS:
3328         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Gt<int32_t>));
3329         break;
3330 
3331       case Opcode::I32X4GtU:
3332         CHECK_TRAP(SimdRelBinop<v128, uint32_t>(Gt<uint32_t>));
3333         break;
3334 
3335       case Opcode::F32X4Gt:
3336         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Gt<float>));
3337         break;
3338 
3339       case Opcode::F64X2Gt:
3340         CHECK_TRAP(SimdRelBinop<v128, int64_t>(Gt<double>));
3341         break;
3342 
3343       case Opcode::I8X16GeS:
3344         CHECK_TRAP(SimdRelBinop<v128, int8_t>(Ge<int32_t>));
3345         break;
3346 
3347       case Opcode::I8X16GeU:
3348         CHECK_TRAP(SimdRelBinop<v128, uint8_t>(Ge<uint32_t>));
3349         break;
3350 
3351       case Opcode::I16X8GeS:
3352         CHECK_TRAP(SimdRelBinop<v128, int16_t>(Ge<int32_t>));
3353         break;
3354 
3355       case Opcode::I16X8GeU:
3356         CHECK_TRAP(SimdRelBinop<v128, uint16_t>(Ge<uint32_t>));
3357         break;
3358 
3359       case Opcode::I32X4GeS:
3360         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Ge<int32_t>));
3361         break;
3362 
3363       case Opcode::I32X4GeU:
3364         CHECK_TRAP(SimdRelBinop<v128, uint32_t>(Ge<uint32_t>));
3365         break;
3366 
3367       case Opcode::F32X4Ge:
3368         CHECK_TRAP(SimdRelBinop<v128, int32_t>(Ge<float>));
3369         break;
3370 
3371       case Opcode::F64X2Ge:
3372         CHECK_TRAP(SimdRelBinop<v128, int64_t>(Ge<double>));
3373         break;
3374 
3375       case Opcode::F32X4Neg:
3376         CHECK_TRAP(SimdUnop<v128, int32_t>(FloatNeg<float>));
3377         break;
3378 
3379       case Opcode::F64X2Neg:
3380         CHECK_TRAP(SimdUnop<v128, int64_t>(FloatNeg<double>));
3381         break;
3382 
3383       case Opcode::F32X4Abs:
3384         CHECK_TRAP(SimdUnop<v128, int32_t>(FloatAbs<float>));
3385         break;
3386 
3387       case Opcode::F64X2Abs:
3388         CHECK_TRAP(SimdUnop<v128, int64_t>(FloatAbs<double>));
3389         break;
3390 
3391       case Opcode::F32X4Min:
3392         CHECK_TRAP(SimdBinop<v128, int32_t>(FloatMin<float>));
3393         break;
3394 
3395       case Opcode::F64X2Min:
3396         CHECK_TRAP(SimdBinop<v128, int64_t>(FloatMin<double>));
3397         break;
3398 
3399       case Opcode::F32X4Max:
3400         CHECK_TRAP(SimdBinop<v128, int32_t>(FloatMax<float>));
3401         break;
3402 
3403       case Opcode::F64X2Max:
3404         CHECK_TRAP(SimdBinop<v128, int64_t>(FloatMax<double>));
3405         break;
3406 
3407       case Opcode::F32X4Add:
3408         CHECK_TRAP(SimdBinop<v128, int32_t>(Add<float>));
3409         break;
3410 
3411       case Opcode::F64X2Add:
3412         CHECK_TRAP(SimdBinop<v128, int64_t>(Add<double>));
3413         break;
3414 
3415       case Opcode::F32X4Sub:
3416         CHECK_TRAP(SimdBinop<v128, int32_t>(Sub<float>));
3417         break;
3418 
3419       case Opcode::F64X2Sub:
3420         CHECK_TRAP(SimdBinop<v128, int64_t>(Sub<double>));
3421         break;
3422 
3423       case Opcode::F32X4Div:
3424         CHECK_TRAP(SimdBinop<v128, int32_t>(FloatDiv<float>));
3425         break;
3426 
3427       case Opcode::F64X2Div:
3428         CHECK_TRAP(SimdBinop<v128, int64_t>(FloatDiv<double>));
3429         break;
3430 
3431       case Opcode::F32X4Mul:
3432         CHECK_TRAP(SimdBinop<v128, int32_t>(Mul<float>));
3433         break;
3434 
3435       case Opcode::F64X2Mul:
3436         CHECK_TRAP(SimdBinop<v128, int64_t>(Mul<double>));
3437         break;
3438 
3439       case Opcode::F32X4Sqrt:
3440         CHECK_TRAP(SimdUnop<v128, int32_t>(FloatSqrt<float>));
3441         break;
3442 
3443       case Opcode::F64X2Sqrt:
3444         CHECK_TRAP(SimdUnop<v128, int64_t>(FloatSqrt<double>));
3445         break;
3446 
3447       case Opcode::F32X4ConvertI32X4S:
3448         CHECK_TRAP(SimdUnop<v128, int32_t>(SimdConvert<float, int32_t>));
3449         break;
3450 
3451       case Opcode::F32X4ConvertI32X4U:
3452         CHECK_TRAP(SimdUnop<v128, uint32_t>(SimdConvert<float, uint32_t>));
3453         break;
3454 
3455       case Opcode::F64X2ConvertI64X2S:
3456         CHECK_TRAP(SimdUnop<v128, int64_t>(SimdConvert<double, int64_t>));
3457         break;
3458 
3459       case Opcode::F64X2ConvertI64X2U:
3460         CHECK_TRAP(SimdUnop<v128, uint64_t>(SimdConvert<double, uint64_t>));
3461         break;
3462 
3463       case Opcode::I32X4TruncSatF32X4S:
3464         CHECK_TRAP(SimdUnop<v128, int32_t>(IntTruncSat<int32_t, float>));
3465         break;
3466 
3467       case Opcode::I32X4TruncSatF32X4U:
3468         CHECK_TRAP(SimdUnop<v128, uint32_t>(IntTruncSat<uint32_t, float>));
3469         break;
3470 
3471       case Opcode::I64X2TruncSatF64X2S:
3472         CHECK_TRAP(SimdUnop<v128, int64_t>(IntTruncSat<int64_t, double>));
3473         break;
3474 
3475       case Opcode::I64X2TruncSatF64X2U:
3476         CHECK_TRAP(SimdUnop<v128, uint64_t>(IntTruncSat<uint64_t, double>));
3477         break;
3478 
3479       case Opcode::TableGet:
3480       case Opcode::TableSet:
3481       case Opcode::TableGrow:
3482       case Opcode::TableSize:
3483       case Opcode::RefNull:
3484       case Opcode::RefIsNull:
3485       case Opcode::RefFunc:
3486         WABT_UNREACHABLE;
3487         break;
3488 
3489       case Opcode::MemoryInit:
3490         CHECK_TRAP(MemoryInit(&pc));
3491         break;
3492 
3493       case Opcode::DataDrop:
3494         CHECK_TRAP(DataDrop(&pc));
3495         break;
3496 
3497       case Opcode::MemoryCopy:
3498         CHECK_TRAP(MemoryCopy(&pc));
3499         break;
3500 
3501       case Opcode::MemoryFill:
3502         CHECK_TRAP(MemoryFill(&pc));
3503         break;
3504 
3505       case Opcode::TableInit:
3506         CHECK_TRAP(TableInit(&pc));
3507         break;
3508 
3509       case Opcode::ElemDrop:
3510         CHECK_TRAP(ElemDrop(&pc));
3511         break;
3512 
3513       case Opcode::TableCopy:
3514         CHECK_TRAP(TableCopy(&pc));
3515         break;
3516 
3517       // The following opcodes are either never generated or should never be
3518       // executed.
3519       case Opcode::Block:
3520       case Opcode::BrOnExn:
3521       case Opcode::Catch:
3522       case Opcode::Else:
3523       case Opcode::End:
3524       case Opcode::If:
3525       case Opcode::InterpData:
3526       case Opcode::Invalid:
3527       case Opcode::Loop:
3528       case Opcode::Rethrow:
3529       case Opcode::Throw:
3530       case Opcode::Try:
3531         WABT_UNREACHABLE;
3532         break;
3533     }
3534   }
3535 
3536 exit_loop:
3537   pc_ = pc - istream;
3538   return result;
3539 }
3540 
Executor(Environment * env,Stream * trace_stream,const Thread::Options & options)3541 Executor::Executor(Environment* env,
3542                    Stream* trace_stream,
3543                    const Thread::Options& options)
3544     : env_(env), trace_stream_(trace_stream), thread_(env, options) {}
3545 
RunFunction(Index func_index,const TypedValues & args)3546 ExecResult Executor::RunFunction(Index func_index, const TypedValues& args) {
3547   ExecResult exec_result;
3548   Func* func = env_->GetFunc(func_index);
3549   FuncSignature* sig = env_->GetFuncSignature(func->sig_index);
3550 
3551   thread_.Reset();
3552   exec_result.result = PushArgs(sig, args);
3553   if (exec_result.result == Result::Ok) {
3554     exec_result.result =
3555         func->is_host ? thread_.CallHost(cast<HostFunc>(func))
3556                       : RunDefinedFunction(cast<DefinedFunc>(func)->offset);
3557     if (exec_result.result == Result::Ok) {
3558       CopyResults(sig, &exec_result.values);
3559     }
3560   }
3561 
3562   return exec_result;
3563 }
3564 
RunStartFunction(DefinedModule * module)3565 ExecResult Executor::RunStartFunction(DefinedModule* module) {
3566   if (module->start_func_index == kInvalidIndex) {
3567     return ExecResult(Result::Ok);
3568   }
3569 
3570   if (trace_stream_) {
3571     trace_stream_->Writef(">>> running start function:\n");
3572   }
3573 
3574   TypedValues args;
3575   ExecResult exec_result = RunFunction(module->start_func_index, args);
3576   assert(exec_result.values.size() == 0);
3577   return exec_result;
3578 }
3579 
RunExport(const Export * export_,const TypedValues & args)3580 ExecResult Executor::RunExport(const Export* export_, const TypedValues& args) {
3581   if (trace_stream_) {
3582     trace_stream_->Writef(">>> running export \"" PRIstringview "\":\n",
3583                           WABT_PRINTF_STRING_VIEW_ARG(export_->name));
3584   }
3585 
3586   assert(export_->kind == ExternalKind::Func);
3587   return RunFunction(export_->index, args);
3588 }
3589 
RunExportByName(Module * module,string_view name,const TypedValues & args)3590 ExecResult Executor::RunExportByName(Module* module,
3591                                      string_view name,
3592                                      const TypedValues& args) {
3593   Export* export_ = module->GetExport(name);
3594   if (!export_) {
3595     return ExecResult(Result::UnknownExport);
3596   }
3597   if (export_->kind != ExternalKind::Func) {
3598     return ExecResult(Result::ExportKindMismatch);
3599   }
3600   return RunExport(export_, args);
3601 }
3602 
RunDefinedFunction(IstreamOffset function_offset)3603 Result Executor::RunDefinedFunction(IstreamOffset function_offset) {
3604   Result result = Result::Ok;
3605   thread_.set_pc(function_offset);
3606   if (trace_stream_) {
3607     const int kNumInstructions = 1;
3608     while (result == Result::Ok) {
3609       thread_.Trace(trace_stream_);
3610       result = thread_.Run(kNumInstructions);
3611     }
3612   } else {
3613     const int kNumInstructions = 1000;
3614     while (result == Result::Ok) {
3615       result = thread_.Run(kNumInstructions);
3616     }
3617   }
3618   if (result != Result::Returned) {
3619     return result;
3620   }
3621   // Use OK instead of RETURNED for consistency.
3622   return Result::Ok;
3623 }
3624 
PushArgs(const FuncSignature * sig,const TypedValues & args)3625 Result Executor::PushArgs(const FuncSignature* sig, const TypedValues& args) {
3626   if (sig->param_types.size() != args.size()) {
3627     return Result::ArgumentTypeMismatch;
3628   }
3629 
3630   for (size_t i = 0; i < sig->param_types.size(); ++i) {
3631     if (sig->param_types[i] != args[i].type) {
3632       return Result::ArgumentTypeMismatch;
3633     }
3634 
3635     Result result = thread_.Push(args[i].value);
3636     if (result != Result::Ok) {
3637       return result;
3638     }
3639   }
3640   return Result::Ok;
3641 }
3642 
CopyResults(const FuncSignature * sig,TypedValues * out_results)3643 void Executor::CopyResults(const FuncSignature* sig, TypedValues* out_results) {
3644   size_t expected_results = sig->result_types.size();
3645   assert(expected_results == thread_.NumValues());
3646 
3647   out_results->clear();
3648   for (size_t i = 0; i < expected_results; ++i)
3649     out_results->emplace_back(sig->result_types[i], thread_.ValueAt(i));
3650 }
3651 
3652 }  // namespace interp
3653 }  // namespace wabt
3654