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