Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1552)

Side by Side Diff: src/asmjs/asm-parser.cc

Issue 2771183002: [wasm][asm.js] Fix and enable several asm.js tests with the new parser. (Closed)
Patch Set: fix Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 the V8 project authors. All rights reserved. 1 // Copyright 2017 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/asmjs/asm-parser.h" 5 #include "src/asmjs/asm-parser.h"
6 6
7 // Required to get M_E etc. for MSVC. 7 // Required to get M_E etc. for MSVC.
8 // References from STDLIB_MATH_VALUE_LIST in asm-names.h 8 // References from STDLIB_MATH_VALUE_LIST in asm-names.h
9 #if defined(_WIN32) 9 #if defined(_WIN32)
10 #define _USE_MATH_DEFINES 10 #define _USE_MATH_DEFINES
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 if (info->import != nullptr) { 231 if (info->import != nullptr) {
232 return info->index; 232 return info->index;
233 } else { 233 } else {
234 return info->index + static_cast<uint32_t>(global_imports_.size()); 234 return info->index + static_cast<uint32_t>(global_imports_.size());
235 } 235 }
236 } 236 }
237 237
238 void AsmJsParser::AddGlobalImport(std::string name, AsmType* type, 238 void AsmJsParser::AddGlobalImport(std::string name, AsmType* type,
239 ValueType vtype, bool mutable_variable, 239 ValueType vtype, bool mutable_variable,
240 VarInfo* info) { 240 VarInfo* info) {
241 // TODO(bradnelson): Refactor memory management here.
242 // AsmModuleBuilder should really own import names.
243 char* name_data = zone()->NewArray<char>(name.size());
244 memcpy(name_data, name.data(), name.size());
241 if (mutable_variable) { 245 if (mutable_variable) {
242 // Allocate a separate variable for the import. 246 // Allocate a separate variable for the import.
243 DeclareGlobal(info, true, type, vtype); 247 DeclareGlobal(info, true, type, vtype);
244 // Record the need to initialize the global from the import. 248 // Record the need to initialize the global from the import.
245 global_imports_.push_back({name, 0, info->index, true}); 249 global_imports_.push_back({name_data, name.size(), 0, info->index, true});
246 } else { 250 } else {
247 // Just use the import directly. 251 // Just use the import directly.
248 global_imports_.push_back({name, 0, info->index, false}); 252 global_imports_.push_back({name_data, name.size(), 0, info->index, false});
249 } 253 }
250 GlobalImport& gi = global_imports_.back(); 254 GlobalImport& gi = global_imports_.back();
251 // TODO(bradnelson): Reuse parse buffer memory / make wasm-module-builder 255 // TODO(bradnelson): Reuse parse buffer memory / make wasm-module-builder
252 // managed the memory for the import name (currently have to keep our 256 // managed the memory for the import name (currently have to keep our
253 // own memory for it). 257 // own memory for it).
254 gi.import_index = module_builder_->AddGlobalImport( 258 gi.import_index = module_builder_->AddGlobalImport(
255 name.data(), static_cast<int>(name.size()), vtype); 259 name_data, static_cast<int>(name.size()), vtype);
256 if (!mutable_variable) { 260 if (!mutable_variable) {
257 info->DeclareGlobalImport(type, gi.import_index); 261 info->DeclareGlobalImport(type, gi.import_index);
258 } 262 }
259 } 263 }
260 264
261 void AsmJsParser::VarInfo::DeclareGlobalImport(AsmType* type, uint32_t index) { 265 void AsmJsParser::VarInfo::DeclareGlobalImport(AsmType* type, uint32_t index) {
262 kind = VarKind::kGlobal; 266 kind = VarKind::kGlobal;
263 this->type = type; 267 this->type = type;
264 this->index = index; 268 this->index = index;
265 mutable_variable = false; 269 mutable_variable = false;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 SkipSemicolon(); 359 SkipSemicolon();
356 RECURSE(ValidateModuleVars()); 360 RECURSE(ValidateModuleVars());
357 while (Peek(TOK(function))) { 361 while (Peek(TOK(function))) {
358 RECURSE(ValidateFunction()); 362 RECURSE(ValidateFunction());
359 } 363 }
360 while (Peek(TOK(var))) { 364 while (Peek(TOK(var))) {
361 RECURSE(ValidateFunctionTable()); 365 RECURSE(ValidateFunctionTable());
362 } 366 }
363 RECURSE(ValidateExport()); 367 RECURSE(ValidateExport());
364 368
369 // Check that all functions were eventually defined.
370 for (auto info : global_var_info_) {
371 if (info.kind != VarKind::kFunction) {
372 continue;
373 }
374 if (!info.function_defined) {
375 FAIL("Undefined function");
376 }
377 }
378
365 // Add start function to init things. 379 // Add start function to init things.
366 WasmFunctionBuilder* start = module_builder_->AddFunction(); 380 WasmFunctionBuilder* start = module_builder_->AddFunction();
367 module_builder_->MarkStartFunction(start); 381 module_builder_->MarkStartFunction(start);
368 for (auto global_import : global_imports_) { 382 for (auto global_import : global_imports_) {
369 if (global_import.needs_init) { 383 if (global_import.needs_init) {
370 start->EmitWithVarInt(kExprGetGlobal, global_import.import_index); 384 start->EmitWithVarInt(kExprGetGlobal, global_import.import_index);
371 start->EmitWithVarInt(kExprSetGlobal, 385 start->EmitWithVarInt(kExprSetGlobal,
372 static_cast<uint32_t>(global_import.global_index + 386 static_cast<uint32_t>(global_import.global_index +
373 global_imports_.size())); 387 global_imports_.size()));
374 } 388 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 EXPECT_TOKEN('='); 454 EXPECT_TOKEN('=');
441 double dvalue = 0.0; 455 double dvalue = 0.0;
442 uint64_t uvalue = 0; 456 uint64_t uvalue = 0;
443 if (CheckForDouble(&dvalue)) { 457 if (CheckForDouble(&dvalue)) {
444 DeclareGlobal(info, mutable_variable, AsmType::Double(), kWasmF64, 458 DeclareGlobal(info, mutable_variable, AsmType::Double(), kWasmF64,
445 WasmInitExpr(dvalue)); 459 WasmInitExpr(dvalue));
446 } else if (CheckForUnsigned(&uvalue)) { 460 } else if (CheckForUnsigned(&uvalue)) {
447 if (uvalue > 0x7fffffff) { 461 if (uvalue > 0x7fffffff) {
448 FAIL("Numeric literal out of range"); 462 FAIL("Numeric literal out of range");
449 } 463 }
450 DeclareGlobal(info, mutable_variable, AsmType::Int(), kWasmI32, 464 DeclareGlobal(info, mutable_variable,
451 WasmInitExpr(static_cast<int32_t>(uvalue))); 465 mutable_variable ? AsmType::Int() : AsmType::Signed(),
466 kWasmI32, WasmInitExpr(static_cast<int32_t>(uvalue)));
452 } else if (Check('-')) { 467 } else if (Check('-')) {
453 if (CheckForDouble(&dvalue)) { 468 if (CheckForDouble(&dvalue)) {
454 DeclareGlobal(info, mutable_variable, AsmType::Double(), kWasmF64, 469 DeclareGlobal(info, mutable_variable, AsmType::Double(), kWasmF64,
455 WasmInitExpr(-dvalue)); 470 WasmInitExpr(-dvalue));
456 } else if (CheckForUnsigned(&uvalue)) { 471 } else if (CheckForUnsigned(&uvalue)) {
457 if (uvalue > 0x7fffffff) { 472 if (uvalue > 0x7fffffff) {
458 FAIL("Numeric literal out of range"); 473 FAIL("Numeric literal out of range");
459 } 474 }
460 DeclareGlobal(info, mutable_variable, AsmType::Int(), kWasmI32, 475 DeclareGlobal(info, mutable_variable,
461 WasmInitExpr(-static_cast<int32_t>(uvalue))); 476 mutable_variable ? AsmType::Int() : AsmType::Signed(),
477 kWasmI32, WasmInitExpr(-static_cast<int32_t>(uvalue)));
462 } else { 478 } else {
463 FAIL("Expected numeric literal"); 479 FAIL("Expected numeric literal");
464 } 480 }
465 } else if (Check(TOK(new))) { 481 } else if (Check(TOK(new))) {
466 RECURSE(ValidateModuleVarNewStdlib(info)); 482 RECURSE(ValidateModuleVarNewStdlib(info));
467 } else if (Check(stdlib_name_)) { 483 } else if (Check(stdlib_name_)) {
468 EXPECT_TOKEN('.'); 484 EXPECT_TOKEN('.');
469 RECURSE(ValidateModuleVarStdlib(info)); 485 RECURSE(ValidateModuleVarStdlib(info));
470 } else if (ValidateModuleVarImport(info, mutable_variable)) { 486 } else if (ValidateModuleVarImport(info, mutable_variable)) {
471 // Handled inside. 487 // Handled inside.
472 } else if (scanner_.IsGlobal()) { 488 } else if (scanner_.IsGlobal()) {
473 RECURSE(ValidateModuleVarFloat(info, mutable_variable)); 489 RECURSE(ValidateModuleVarFromGlobal(info, mutable_variable));
474 } else { 490 } else {
475 FAIL("Bad variable declaration"); 491 FAIL("Bad variable declaration");
476 } 492 }
477 } 493 }
478 494
479 // 6.1 ValidateModule - global float declaration 495 // 6.1 ValidateModule - global float declaration
480 void AsmJsParser::ValidateModuleVarFloat(VarInfo* info, bool mutable_variable) { 496 void AsmJsParser::ValidateModuleVarFromGlobal(VarInfo* info,
481 if (!GetVarInfo(Consume())->type->IsA(stdlib_fround_)) { 497 bool mutable_variable) {
482 FAIL("Expected fround"); 498 VarInfo* src_info = GetVarInfo(Consume());
499 if (!src_info->type->IsA(stdlib_fround_)) {
500 if (src_info->mutable_variable) {
501 FAIL("Can only use immutable variables in global definition");
502 }
503 if (mutable_variable) {
504 FAIL("Can only define immutable variables with other immutables");
505 }
506 if (!src_info->type->IsA(AsmType::Int()) &&
507 !src_info->type->IsA(AsmType::Float()) &&
508 !src_info->type->IsA(AsmType::Double())) {
509 FAIL("Expected int, float, double, or fround for global definition");
510 }
511 info->kind = VarKind::kGlobal;
512 info->type = src_info->type;
513 info->index = src_info->index;
514 info->mutable_variable = false;
515 return;
483 } 516 }
484 EXPECT_TOKEN('('); 517 EXPECT_TOKEN('(');
485 bool negate = false; 518 bool negate = false;
486 if (Check('-')) { 519 if (Check('-')) {
487 negate = true; 520 negate = true;
488 } 521 }
489 double dvalue = 0.0; 522 double dvalue = 0.0;
490 uint64_t uvalue = 0; 523 uint64_t uvalue = 0;
491 if (CheckForDouble(&dvalue)) { 524 if (CheckForDouble(&dvalue)) {
492 if (negate) { 525 if (negate) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 if (!CheckForZero()) { 558 if (!CheckForZero()) {
526 FAILf("Expected |0 type annotation for foreign integer import"); 559 FAILf("Expected |0 type annotation for foreign integer import");
527 } 560 }
528 AddGlobalImport(import_name, AsmType::Int(), kWasmI32, mutable_variable, 561 AddGlobalImport(import_name, AsmType::Int(), kWasmI32, mutable_variable,
529 info); 562 info);
530 return true; 563 return true;
531 } 564 }
532 info->kind = VarKind::kImportedFunction; 565 info->kind = VarKind::kImportedFunction;
533 function_import_info_.resize(function_import_info_.size() + 1); 566 function_import_info_.resize(function_import_info_.size() + 1);
534 info->import = &function_import_info_.back(); 567 info->import = &function_import_info_.back();
535 info->import->name = import_name; 568 // TODO(bradnelson): Refactor memory management here.
569 // AsmModuleBuilder should really own import names.
570 info->import->function_name = zone()->NewArray<char>(import_name.size());
571 memcpy(info->import->function_name, import_name.data(), import_name.size());
572 info->import->function_name_size = import_name.size();
536 return true; 573 return true;
537 } 574 }
538 return false; 575 return false;
539 } 576 }
540 577
541 // 6.1 ValidateModule - one variable 578 // 6.1 ValidateModule - one variable
542 // 9 - Standard Library - heap types 579 // 9 - Standard Library - heap types
543 void AsmJsParser::ValidateModuleVarNewStdlib(VarInfo* info) { 580 void AsmJsParser::ValidateModuleVarNewStdlib(VarInfo* info) {
544 EXPECT_TOKEN(stdlib_name_); 581 EXPECT_TOKEN(stdlib_name_);
545 EXPECT_TOKEN('.'); 582 EXPECT_TOKEN('.');
(...skipping 16 matching lines...) Expand all
562 // 6.1 ValidateModule - one variable 599 // 6.1 ValidateModule - one variable
563 // 9 - Standard Library 600 // 9 - Standard Library
564 void AsmJsParser::ValidateModuleVarStdlib(VarInfo* info) { 601 void AsmJsParser::ValidateModuleVarStdlib(VarInfo* info) {
565 if (Check(TOK(Math))) { 602 if (Check(TOK(Math))) {
566 EXPECT_TOKEN('.'); 603 EXPECT_TOKEN('.');
567 switch (Consume()) { 604 switch (Consume()) {
568 #define V(name) \ 605 #define V(name) \
569 case TOK(name): \ 606 case TOK(name): \
570 DeclareGlobal(info, false, AsmType::Double(), kWasmF64, \ 607 DeclareGlobal(info, false, AsmType::Double(), kWasmF64, \
571 WasmInitExpr(M_##name)); \ 608 WasmInitExpr(M_##name)); \
609 stdlib_uses_.insert(AsmTyper::kMath##name); \
572 break; 610 break;
573 STDLIB_MATH_VALUE_LIST(V) 611 STDLIB_MATH_VALUE_LIST(V)
574 #undef V 612 #undef V
575 #define V(name, Name, op, sig) \ 613 #define V(name, Name, op, sig) \
576 case TOK(name): \ 614 case TOK(name): \
577 info->DeclareStdlibFunc(VarKind::kMath##Name, stdlib_##sig##_); \ 615 info->DeclareStdlibFunc(VarKind::kMath##Name, stdlib_##sig##_); \
578 stdlib_uses_.insert(AsmTyper::kMath##Name); \ 616 stdlib_uses_.insert(AsmTyper::kMath##Name); \
579 break; 617 break;
580 STDLIB_MATH_FUNCTION_LIST(V) 618 STDLIB_MATH_FUNCTION_LIST(V)
581 #undef V 619 #undef V
582 default: 620 default:
583 FAIL("Invalid member of stdlib.Math"); 621 FAIL("Invalid member of stdlib.Math");
584 } 622 }
585 } else if (Check(TOK(Infinity))) { 623 } else if (Check(TOK(Infinity))) {
586 DeclareGlobal(info, false, AsmType::Double(), kWasmF64, 624 DeclareGlobal(info, false, AsmType::Double(), kWasmF64,
587 WasmInitExpr(std::numeric_limits<double>::infinity())); 625 WasmInitExpr(std::numeric_limits<double>::infinity()));
626 stdlib_uses_.insert(AsmTyper::kInfinity);
588 } else if (Check(TOK(NaN))) { 627 } else if (Check(TOK(NaN))) {
589 DeclareGlobal(info, false, AsmType::Double(), kWasmF64, 628 DeclareGlobal(info, false, AsmType::Double(), kWasmF64,
590 WasmInitExpr(std::numeric_limits<double>::quiet_NaN())); 629 WasmInitExpr(std::numeric_limits<double>::quiet_NaN()));
630 stdlib_uses_.insert(AsmTyper::kNaN);
591 } else { 631 } else {
592 FAIL("Invalid member of stdlib"); 632 FAIL("Invalid member of stdlib");
593 } 633 }
594 } 634 }
595 635
596 // 6.2 ValidateExport 636 // 6.2 ValidateExport
597 void AsmJsParser::ValidateExport() { 637 void AsmJsParser::ValidateExport() {
598 // clang-format off 638 // clang-format off
599 EXPECT_TOKEN(TOK(return)); 639 EXPECT_TOKEN(TOK(return));
600 // clang format on 640 // clang format on
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 if (!scanner_.IsGlobal()) { 728 if (!scanner_.IsGlobal()) {
689 FAIL("Expected function name"); 729 FAIL("Expected function name");
690 } 730 }
691 731
692 std::string function_name_raw = scanner_.GetIdentifierString(); 732 std::string function_name_raw = scanner_.GetIdentifierString();
693 AsmJsScanner::token_t function_name = Consume(); 733 AsmJsScanner::token_t function_name = Consume();
694 VarInfo* function_info = GetVarInfo(function_name); 734 VarInfo* function_info = GetVarInfo(function_name);
695 if (function_info->kind == VarKind::kUnused) { 735 if (function_info->kind == VarKind::kUnused) {
696 function_info->kind = VarKind::kFunction; 736 function_info->kind = VarKind::kFunction;
697 function_info->function_builder = module_builder_->AddFunction(); 737 function_info->function_builder = module_builder_->AddFunction();
738 // TODO(bradnelson): Cleanup memory management here.
739 // WasmModuleBuilder should own these.
740 char* function_name = zone()->NewArray<char>(function_name_raw.size());
741 memcpy(function_name, function_name_raw.data(), function_name_raw.size());
698 function_info->function_builder->SetName( 742 function_info->function_builder->SetName(
699 {function_name_raw.c_str(), 743 {function_name, static_cast<int>(function_name_raw.size())});
700 static_cast<int>(function_name_raw.size())});
701 function_info->index = function_info->function_builder->func_index(); 744 function_info->index = function_info->function_builder->func_index();
702 function_info->function_defined = true; 745 function_info->function_defined = true;
703 } else if (function_info->function_defined) { 746 } else if (function_info->function_defined) {
704 FAIL("Function redefined"); 747 FAIL("Function redefined");
748 } else {
749 function_info->function_defined = true;
705 } 750 }
706 current_function_builder_ = function_info->function_builder; 751 current_function_builder_ = function_info->function_builder;
707 return_type_ = nullptr; 752 return_type_ = nullptr;
708 753
709 // Record start of the function, used as position for the stack check. 754 // Record start of the function, used as position for the stack check.
710 current_function_builder_->SetAsmFunctionStartPosition(start_position); 755 current_function_builder_->SetAsmFunctionStartPosition(start_position);
711 756
712 std::vector<AsmType*> params; 757 std::vector<AsmType*> params;
713 ValidateFunctionParams(&params); 758 ValidateFunctionParams(&params);
714 std::vector<ValueType> locals; 759 std::vector<ValueType> locals;
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 // Store types. 893 // Store types.
849 EXPECT_TOKEN('='); 894 EXPECT_TOKEN('=');
850 double dvalue = 0.0; 895 double dvalue = 0.0;
851 uint64_t uvalue = 0; 896 uint64_t uvalue = 0;
852 if (Check('-')) { 897 if (Check('-')) {
853 if (CheckForDouble(&dvalue)) { 898 if (CheckForDouble(&dvalue)) {
854 info->kind = VarKind::kLocal; 899 info->kind = VarKind::kLocal;
855 info->type = AsmType::Double(); 900 info->type = AsmType::Double();
856 info->index = static_cast<uint32_t>(param_count + locals->size()); 901 info->index = static_cast<uint32_t>(param_count + locals->size());
857 locals->push_back(kWasmF64); 902 locals->push_back(kWasmF64);
858 byte code[] = {WASM_F64(dvalue)}; 903 byte code[] = {WASM_F64(-dvalue)};
859 current_function_builder_->EmitCode(code, sizeof(code)); 904 current_function_builder_->EmitCode(code, sizeof(code));
860 current_function_builder_->EmitSetLocal(info->index); 905 current_function_builder_->EmitSetLocal(info->index);
861 } else if (CheckForUnsigned(&uvalue)) { 906 } else if (CheckForUnsigned(&uvalue)) {
862 if (uvalue > 0x7fffffff) { 907 if (uvalue > 0x7fffffff) {
863 FAIL("Numeric literal out of range"); 908 FAIL("Numeric literal out of range");
864 } 909 }
865 info->kind = VarKind::kLocal; 910 info->kind = VarKind::kLocal;
866 info->type = AsmType::Int(); 911 info->type = AsmType::Int();
867 info->index = static_cast<uint32_t>(param_count + locals->size()); 912 info->index = static_cast<uint32_t>(param_count + locals->size());
868 locals->push_back(kWasmI32); 913 locals->push_back(kWasmI32);
(...skipping 1187 matching lines...) Expand 10 before | Expand all | Expand 10 after
2056 } 2101 }
2057 if (return_type->IsA(AsmType::Float())) { 2102 if (return_type->IsA(AsmType::Float())) {
2058 FAILn("Imported function can't be called as float"); 2103 FAILn("Imported function can't be called as float");
2059 } 2104 }
2060 DCHECK(function_info->import != nullptr); 2105 DCHECK(function_info->import != nullptr);
2061 // TODO(bradnelson): Factor out. 2106 // TODO(bradnelson): Factor out.
2062 uint32_t cache_index = function_info->import->cache.FindOrInsert(sig); 2107 uint32_t cache_index = function_info->import->cache.FindOrInsert(sig);
2063 uint32_t index; 2108 uint32_t index;
2064 if (cache_index >= function_info->import->cache_index.size()) { 2109 if (cache_index >= function_info->import->cache_index.size()) {
2065 index = module_builder_->AddImport( 2110 index = module_builder_->AddImport(
2066 function_info->import->name.data(), 2111 function_info->import->function_name,
2067 static_cast<uint32_t>(function_info->import->name.size()), sig); 2112 static_cast<uint32_t>(function_info->import->function_name_size),
2113 sig);
2068 function_info->import->cache_index.push_back(index); 2114 function_info->import->cache_index.push_back(index);
2069 } else { 2115 } else {
2070 index = function_info->import->cache_index[cache_index]; 2116 index = function_info->import->cache_index[cache_index];
2071 } 2117 }
2072 current_function_builder_->Emit(kExprCallFunction); 2118 current_function_builder_->Emit(kExprCallFunction);
2073 current_function_builder_->EmitVarUint(index); 2119 current_function_builder_->EmitVarUint(index);
2074 } else if (function_info->type->IsA(AsmType::None())) { 2120 } else if (function_info->type->IsA(AsmType::None())) {
2075 function_info->type = function_type; 2121 function_info->type = function_type;
2076 if (function_info->kind == VarKind::kTable) { 2122 if (function_info->kind == VarKind::kTable) {
2077 current_function_builder_->EmitGetLocal(tmp); 2123 current_function_builder_->EmitGetLocal(tmp);
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
2366 break; 2412 break;
2367 } 2413 }
2368 scanner_.Next(); 2414 scanner_.Next();
2369 } 2415 }
2370 scanner_.Seek(start); 2416 scanner_.Seek(start);
2371 } 2417 }
2372 2418
2373 } // namespace wasm 2419 } // namespace wasm
2374 } // namespace internal 2420 } // namespace internal
2375 } // namespace v8 2421 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698