OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/wasm/module-decoder.h" | 5 #include "src/wasm/module-decoder.h" |
6 | 6 |
7 #include "src/base/functional.h" | 7 #include "src/base/functional.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/flags.h" | 9 #include "src/flags.h" |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 } while (false) | 25 } while (false) |
26 #else | 26 #else |
27 #define TRACE(...) | 27 #define TRACE(...) |
28 #endif | 28 #endif |
29 | 29 |
30 namespace { | 30 namespace { |
31 | 31 |
32 const char* kNameString = "name"; | 32 const char* kNameString = "name"; |
33 const size_t kNameStringLength = 4; | 33 const size_t kNameStringLength = 4; |
34 | 34 |
35 LocalType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { | 35 ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { |
36 switch (expr.kind) { | 36 switch (expr.kind) { |
37 case WasmInitExpr::kNone: | 37 case WasmInitExpr::kNone: |
38 return kAstStmt; | 38 return kWasmStmt; |
39 case WasmInitExpr::kGlobalIndex: | 39 case WasmInitExpr::kGlobalIndex: |
40 return expr.val.global_index < module->globals.size() | 40 return expr.val.global_index < module->globals.size() |
41 ? module->globals[expr.val.global_index].type | 41 ? module->globals[expr.val.global_index].type |
42 : kAstStmt; | 42 : kWasmStmt; |
43 case WasmInitExpr::kI32Const: | 43 case WasmInitExpr::kI32Const: |
44 return kAstI32; | 44 return kWasmI32; |
45 case WasmInitExpr::kI64Const: | 45 case WasmInitExpr::kI64Const: |
46 return kAstI64; | 46 return kWasmI64; |
47 case WasmInitExpr::kF32Const: | 47 case WasmInitExpr::kF32Const: |
48 return kAstF32; | 48 return kWasmF32; |
49 case WasmInitExpr::kF64Const: | 49 case WasmInitExpr::kF64Const: |
50 return kAstF64; | 50 return kWasmF64; |
51 default: | 51 default: |
52 UNREACHABLE(); | 52 UNREACHABLE(); |
53 return kAstStmt; | 53 return kWasmStmt; |
54 } | 54 } |
55 } | 55 } |
56 | 56 |
57 // An iterator over the sections in a WASM binary module. | 57 // An iterator over the sections in a WASM binary module. |
58 // Automatically skips all unknown sections. | 58 // Automatically skips all unknown sections. |
59 class WasmSectionIterator { | 59 class WasmSectionIterator { |
60 public: | 60 public: |
61 explicit WasmSectionIterator(Decoder& decoder) | 61 explicit WasmSectionIterator(Decoder& decoder) |
62 : decoder_(decoder), | 62 : decoder_(decoder), |
63 section_code_(kUnknownSectionCode), | 63 section_code_(kUnknownSectionCode), |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 &module->min_mem_pages, &has_max, | 324 &module->min_mem_pages, &has_max, |
325 kSpecMaxWasmMemoryPages, | 325 kSpecMaxWasmMemoryPages, |
326 &module->max_mem_pages); | 326 &module->max_mem_pages); |
327 module->has_memory = true; | 327 module->has_memory = true; |
328 break; | 328 break; |
329 } | 329 } |
330 case kExternalGlobal: { | 330 case kExternalGlobal: { |
331 // ===== Imported global ========================================= | 331 // ===== Imported global ========================================= |
332 import->index = static_cast<uint32_t>(module->globals.size()); | 332 import->index = static_cast<uint32_t>(module->globals.size()); |
333 module->globals.push_back( | 333 module->globals.push_back( |
334 {kAstStmt, false, WasmInitExpr(), 0, true, false}); | 334 {kWasmStmt, false, WasmInitExpr(), 0, true, false}); |
335 WasmGlobal* global = &module->globals.back(); | 335 WasmGlobal* global = &module->globals.back(); |
336 global->type = consume_value_type(); | 336 global->type = consume_value_type(); |
337 global->mutability = consume_u8("mutability") != 0; | 337 global->mutability = consume_u8("mutability") != 0; |
338 if (global->mutability) { | 338 if (global->mutability) { |
339 error("mutable globals cannot be imported"); | 339 error("mutable globals cannot be imported"); |
340 } | 340 } |
341 break; | 341 break; |
342 } | 342 } |
343 default: | 343 default: |
344 error(pos, pos, "unknown import kind 0x%02x", import->kind); | 344 error(pos, pos, "unknown import kind 0x%02x", import->kind); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 if (section_iter.section_code() == kGlobalSectionCode) { | 407 if (section_iter.section_code() == kGlobalSectionCode) { |
408 uint32_t globals_count = | 408 uint32_t globals_count = |
409 consume_count("globals count", kV8MaxWasmGlobals); | 409 consume_count("globals count", kV8MaxWasmGlobals); |
410 uint32_t imported_globals = static_cast<uint32_t>(module->globals.size()); | 410 uint32_t imported_globals = static_cast<uint32_t>(module->globals.size()); |
411 module->globals.reserve(imported_globals + globals_count); | 411 module->globals.reserve(imported_globals + globals_count); |
412 for (uint32_t i = 0; ok() && i < globals_count; ++i) { | 412 for (uint32_t i = 0; ok() && i < globals_count; ++i) { |
413 TRACE("DecodeGlobal[%d] module+%d\n", i, | 413 TRACE("DecodeGlobal[%d] module+%d\n", i, |
414 static_cast<int>(pc_ - start_)); | 414 static_cast<int>(pc_ - start_)); |
415 // Add an uninitialized global and pass a pointer to it. | 415 // Add an uninitialized global and pass a pointer to it. |
416 module->globals.push_back( | 416 module->globals.push_back( |
417 {kAstStmt, false, WasmInitExpr(), 0, false, false}); | 417 {kWasmStmt, false, WasmInitExpr(), 0, false, false}); |
418 WasmGlobal* global = &module->globals.back(); | 418 WasmGlobal* global = &module->globals.back(); |
419 DecodeGlobalInModule(module, i + imported_globals, global); | 419 DecodeGlobalInModule(module, i + imported_globals, global); |
420 } | 420 } |
421 section_iter.advance(); | 421 section_iter.advance(); |
422 } | 422 } |
423 | 423 |
424 // ===== Export section ================================================== | 424 // ===== Export section ================================================== |
425 if (section_iter.section_code() == kExportSectionCode) { | 425 if (section_iter.section_code() == kExportSectionCode) { |
426 uint32_t export_table_count = | 426 uint32_t export_table_count = |
427 consume_count("exports count", kV8MaxWasmImports); | 427 consume_count("exports count", kV8MaxWasmImports); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 uint32_t table_index = consume_u32v("table index"); | 529 uint32_t table_index = consume_u32v("table index"); |
530 if (table_index != 0) { | 530 if (table_index != 0) { |
531 error(pos, pos, "illegal table index %u != 0", table_index); | 531 error(pos, pos, "illegal table index %u != 0", table_index); |
532 } | 532 } |
533 WasmIndirectFunctionTable* table = nullptr; | 533 WasmIndirectFunctionTable* table = nullptr; |
534 if (table_index >= module->function_tables.size()) { | 534 if (table_index >= module->function_tables.size()) { |
535 error(pos, pos, "out of bounds table index %u", table_index); | 535 error(pos, pos, "out of bounds table index %u", table_index); |
536 } else { | 536 } else { |
537 table = &module->function_tables[table_index]; | 537 table = &module->function_tables[table_index]; |
538 } | 538 } |
539 WasmInitExpr offset = consume_init_expr(module, kAstI32); | 539 WasmInitExpr offset = consume_init_expr(module, kWasmI32); |
540 uint32_t num_elem = | 540 uint32_t num_elem = |
541 consume_count("number of elements", kV8MaxWasmTableEntries); | 541 consume_count("number of elements", kV8MaxWasmTableEntries); |
542 std::vector<uint32_t> vector; | 542 std::vector<uint32_t> vector; |
543 module->table_inits.push_back({table_index, offset, vector}); | 543 module->table_inits.push_back({table_index, offset, vector}); |
544 WasmTableInit* init = &module->table_inits.back(); | 544 WasmTableInit* init = &module->table_inits.back(); |
545 for (uint32_t j = 0; ok() && j < num_elem; j++) { | 545 for (uint32_t j = 0; ok() && j < num_elem; j++) { |
546 WasmFunction* func = nullptr; | 546 WasmFunction* func = nullptr; |
547 uint32_t index = consume_func_index(module, &func); | 547 uint32_t index = consume_func_index(module, &func); |
548 init->entries.push_back(index); | 548 init->entries.push_back(index); |
549 if (table && index < module->functions.size()) { | 549 if (table && index < module->functions.size()) { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 | 663 |
664 // Decodes a single function signature at {start}. | 664 // Decodes a single function signature at {start}. |
665 FunctionSig* DecodeFunctionSignature(const byte* start) { | 665 FunctionSig* DecodeFunctionSignature(const byte* start) { |
666 pc_ = start; | 666 pc_ = start; |
667 FunctionSig* result = consume_sig(); | 667 FunctionSig* result = consume_sig(); |
668 return ok() ? result : nullptr; | 668 return ok() ? result : nullptr; |
669 } | 669 } |
670 | 670 |
671 WasmInitExpr DecodeInitExpr(const byte* start) { | 671 WasmInitExpr DecodeInitExpr(const byte* start) { |
672 pc_ = start; | 672 pc_ = start; |
673 return consume_init_expr(nullptr, kAstStmt); | 673 return consume_init_expr(nullptr, kWasmStmt); |
674 } | 674 } |
675 | 675 |
676 private: | 676 private: |
677 Zone* module_zone; | 677 Zone* module_zone; |
678 ModuleResult result_; | 678 ModuleResult result_; |
679 ModuleOrigin origin_; | 679 ModuleOrigin origin_; |
680 | 680 |
681 uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); } | 681 uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); } |
682 | 682 |
683 // Decodes a single global entry inside a module starting at {pc_}. | 683 // Decodes a single global entry inside a module starting at {pc_}. |
684 void DecodeGlobalInModule(WasmModule* module, uint32_t index, | 684 void DecodeGlobalInModule(WasmModule* module, uint32_t index, |
685 WasmGlobal* global) { | 685 WasmGlobal* global) { |
686 global->type = consume_value_type(); | 686 global->type = consume_value_type(); |
687 global->mutability = consume_u8("mutability") != 0; | 687 global->mutability = consume_u8("mutability") != 0; |
688 const byte* pos = pc(); | 688 const byte* pos = pc(); |
689 global->init = consume_init_expr(module, kAstStmt); | 689 global->init = consume_init_expr(module, kWasmStmt); |
690 switch (global->init.kind) { | 690 switch (global->init.kind) { |
691 case WasmInitExpr::kGlobalIndex: { | 691 case WasmInitExpr::kGlobalIndex: { |
692 uint32_t other_index = global->init.val.global_index; | 692 uint32_t other_index = global->init.val.global_index; |
693 if (other_index >= index) { | 693 if (other_index >= index) { |
694 error(pos, pos, | 694 error(pos, pos, |
695 "invalid global index in init expression, " | 695 "invalid global index in init expression, " |
696 "index %u, other_index %u", | 696 "index %u, other_index %u", |
697 index, other_index); | 697 index, other_index); |
698 } else if (module->globals[other_index].type != global->type) { | 698 } else if (module->globals[other_index].type != global->type) { |
699 error(pos, pos, | 699 error(pos, pos, |
(...skipping 17 matching lines...) Expand all Loading... |
717 bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) { | 717 bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) { |
718 if (offset > limit) return false; | 718 if (offset > limit) return false; |
719 if ((offset + size) < offset) return false; // overflow | 719 if ((offset + size) < offset) return false; // overflow |
720 return (offset + size) <= limit; | 720 return (offset + size) <= limit; |
721 } | 721 } |
722 | 722 |
723 // Decodes a single data segment entry inside a module starting at {pc_}. | 723 // Decodes a single data segment entry inside a module starting at {pc_}. |
724 void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) { | 724 void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) { |
725 const byte* start = pc_; | 725 const byte* start = pc_; |
726 expect_u8("linear memory index", 0); | 726 expect_u8("linear memory index", 0); |
727 segment->dest_addr = consume_init_expr(module, kAstI32); | 727 segment->dest_addr = consume_init_expr(module, kWasmI32); |
728 segment->source_size = consume_u32v("source size"); | 728 segment->source_size = consume_u32v("source size"); |
729 segment->source_offset = static_cast<uint32_t>(pc_ - start_); | 729 segment->source_offset = static_cast<uint32_t>(pc_ - start_); |
730 | 730 |
731 // Validate the data is in the module. | 731 // Validate the data is in the module. |
732 uint32_t module_limit = static_cast<uint32_t>(limit_ - start_); | 732 uint32_t module_limit = static_cast<uint32_t>(limit_ - start_); |
733 if (!IsWithinLimit(module_limit, segment->source_offset, | 733 if (!IsWithinLimit(module_limit, segment->source_offset, |
734 segment->source_size)) { | 734 segment->source_size)) { |
735 error(start, "segment out of bounds of module"); | 735 error(start, "segment out of bounds of module"); |
736 } | 736 } |
737 | 737 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 bool expect_u8(const char* name, uint8_t expected) { | 893 bool expect_u8(const char* name, uint8_t expected) { |
894 const byte* pos = pc(); | 894 const byte* pos = pc(); |
895 uint8_t value = consume_u8(name); | 895 uint8_t value = consume_u8(name); |
896 if (value != expected) { | 896 if (value != expected) { |
897 error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value); | 897 error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value); |
898 return false; | 898 return false; |
899 } | 899 } |
900 return true; | 900 return true; |
901 } | 901 } |
902 | 902 |
903 WasmInitExpr consume_init_expr(WasmModule* module, LocalType expected) { | 903 WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) { |
904 const byte* pos = pc(); | 904 const byte* pos = pc(); |
905 uint8_t opcode = consume_u8("opcode"); | 905 uint8_t opcode = consume_u8("opcode"); |
906 WasmInitExpr expr; | 906 WasmInitExpr expr; |
907 unsigned len = 0; | 907 unsigned len = 0; |
908 switch (opcode) { | 908 switch (opcode) { |
909 case kExprGetGlobal: { | 909 case kExprGetGlobal: { |
910 GlobalIndexOperand operand(this, pc() - 1); | 910 GlobalIndexOperand operand(this, pc() - 1); |
911 if (module->globals.size() <= operand.index) { | 911 if (module->globals.size() <= operand.index) { |
912 error("global index is out of bounds"); | 912 error("global index is out of bounds"); |
913 expr.kind = WasmInitExpr::kNone; | 913 expr.kind = WasmInitExpr::kNone; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 default: { | 959 default: { |
960 error("invalid opcode in initialization expression"); | 960 error("invalid opcode in initialization expression"); |
961 expr.kind = WasmInitExpr::kNone; | 961 expr.kind = WasmInitExpr::kNone; |
962 expr.val.i32_const = 0; | 962 expr.val.i32_const = 0; |
963 } | 963 } |
964 } | 964 } |
965 consume_bytes(len, "init code"); | 965 consume_bytes(len, "init code"); |
966 if (!expect_u8("end opcode", kExprEnd)) { | 966 if (!expect_u8("end opcode", kExprEnd)) { |
967 expr.kind = WasmInitExpr::kNone; | 967 expr.kind = WasmInitExpr::kNone; |
968 } | 968 } |
969 if (expected != kAstStmt && TypeOf(module, expr) != kAstI32) { | 969 if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) { |
970 error(pos, pos, "type error in init expression, expected %s, got %s", | 970 error(pos, pos, "type error in init expression, expected %s, got %s", |
971 WasmOpcodes::TypeName(expected), | 971 WasmOpcodes::TypeName(expected), |
972 WasmOpcodes::TypeName(TypeOf(module, expr))); | 972 WasmOpcodes::TypeName(TypeOf(module, expr))); |
973 } | 973 } |
974 return expr; | 974 return expr; |
975 } | 975 } |
976 | 976 |
977 // Reads a single 8-bit integer, interpreting it as a local type. | 977 // Reads a single 8-bit integer, interpreting it as a local type. |
978 LocalType consume_value_type() { | 978 ValueType consume_value_type() { |
979 byte val = consume_u8("value type"); | 979 byte val = consume_u8("value type"); |
980 LocalTypeCode t = static_cast<LocalTypeCode>(val); | 980 ValueTypeCode t = static_cast<ValueTypeCode>(val); |
981 switch (t) { | 981 switch (t) { |
982 case kLocalI32: | 982 case kLocalI32: |
983 return kAstI32; | 983 return kWasmI32; |
984 case kLocalI64: | 984 case kLocalI64: |
985 return kAstI64; | 985 return kWasmI64; |
986 case kLocalF32: | 986 case kLocalF32: |
987 return kAstF32; | 987 return kWasmF32; |
988 case kLocalF64: | 988 case kLocalF64: |
989 return kAstF64; | 989 return kWasmF64; |
990 case kLocalS128: | 990 case kLocalS128: |
991 if (origin_ != kAsmJsOrigin && FLAG_wasm_simd_prototype) { | 991 if (origin_ != kAsmJsOrigin && FLAG_wasm_simd_prototype) { |
992 return kAstS128; | 992 return kWasmS128; |
993 } else { | 993 } else { |
994 error(pc_ - 1, "invalid local type"); | 994 error(pc_ - 1, "invalid local type"); |
995 return kAstStmt; | 995 return kWasmStmt; |
996 } | 996 } |
997 default: | 997 default: |
998 error(pc_ - 1, "invalid local type"); | 998 error(pc_ - 1, "invalid local type"); |
999 return kAstStmt; | 999 return kWasmStmt; |
1000 } | 1000 } |
1001 } | 1001 } |
1002 | 1002 |
1003 // Parses a type entry, which is currently limited to functions only. | 1003 // Parses a type entry, which is currently limited to functions only. |
1004 FunctionSig* consume_sig() { | 1004 FunctionSig* consume_sig() { |
1005 if (!expect_u8("type form", kWasmFunctionTypeForm)) return nullptr; | 1005 if (!expect_u8("type form", kWasmFunctionTypeForm)) return nullptr; |
1006 // parse parameter types | 1006 // parse parameter types |
1007 uint32_t param_count = | 1007 uint32_t param_count = |
1008 consume_count("param count", kV8MaxWasmFunctionParams); | 1008 consume_count("param count", kV8MaxWasmFunctionParams); |
1009 if (failed()) return nullptr; | 1009 if (failed()) return nullptr; |
1010 std::vector<LocalType> params; | 1010 std::vector<ValueType> params; |
1011 for (uint32_t i = 0; ok() && i < param_count; ++i) { | 1011 for (uint32_t i = 0; ok() && i < param_count; ++i) { |
1012 LocalType param = consume_value_type(); | 1012 ValueType param = consume_value_type(); |
1013 params.push_back(param); | 1013 params.push_back(param); |
1014 } | 1014 } |
1015 | 1015 |
1016 // parse return types | 1016 // parse return types |
1017 const size_t max_return_count = FLAG_wasm_mv_prototype | 1017 const size_t max_return_count = FLAG_wasm_mv_prototype |
1018 ? kV8MaxWasmFunctionMultiReturns | 1018 ? kV8MaxWasmFunctionMultiReturns |
1019 : kV8MaxWasmFunctionReturns; | 1019 : kV8MaxWasmFunctionReturns; |
1020 uint32_t return_count = consume_count("return count", max_return_count); | 1020 uint32_t return_count = consume_count("return count", max_return_count); |
1021 if (failed()) return nullptr; | 1021 if (failed()) return nullptr; |
1022 std::vector<LocalType> returns; | 1022 std::vector<ValueType> returns; |
1023 for (uint32_t i = 0; ok() && i < return_count; ++i) { | 1023 for (uint32_t i = 0; ok() && i < return_count; ++i) { |
1024 LocalType ret = consume_value_type(); | 1024 ValueType ret = consume_value_type(); |
1025 returns.push_back(ret); | 1025 returns.push_back(ret); |
1026 } | 1026 } |
1027 | 1027 |
1028 if (failed()) return nullptr; | 1028 if (failed()) return nullptr; |
1029 | 1029 |
1030 // FunctionSig stores the return types first. | 1030 // FunctionSig stores the return types first. |
1031 LocalType* buffer = | 1031 ValueType* buffer = |
1032 module_zone->NewArray<LocalType>(param_count + return_count); | 1032 module_zone->NewArray<ValueType>(param_count + return_count); |
1033 uint32_t b = 0; | 1033 uint32_t b = 0; |
1034 for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i]; | 1034 for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i]; |
1035 for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i]; | 1035 for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i]; |
1036 | 1036 |
1037 return new (module_zone) FunctionSig(return_count, param_count, buffer); | 1037 return new (module_zone) FunctionSig(return_count, param_count, buffer); |
1038 } | 1038 } |
1039 }; | 1039 }; |
1040 | 1040 |
1041 // Helpers for nice error messages. | 1041 // Helpers for nice error messages. |
1042 class ModuleError : public ModuleResult { | 1042 class ModuleError : public ModuleResult { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1221 table.push_back(std::move(func_asm_offsets)); | 1221 table.push_back(std::move(func_asm_offsets)); |
1222 } | 1222 } |
1223 if (decoder.more()) decoder.error("unexpected additional bytes"); | 1223 if (decoder.more()) decoder.error("unexpected additional bytes"); |
1224 | 1224 |
1225 return decoder.toResult(std::move(table)); | 1225 return decoder.toResult(std::move(table)); |
1226 } | 1226 } |
1227 | 1227 |
1228 } // namespace wasm | 1228 } // namespace wasm |
1229 } // namespace internal | 1229 } // namespace internal |
1230 } // namespace v8 | 1230 } // namespace v8 |
OLD | NEW |