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

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

Issue 2398023002: [wasm] asm.js - Parse and convert asm.js to wasm a function at a time. (Closed)
Patch Set: fix Created 4 years 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
« no previous file with comments | « src/asmjs/asm-typer.h ('k') | src/asmjs/asm-wasm-builder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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-typer.h" 5 #include "src/asmjs/asm-typer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <memory> 9 #include <memory>
10 #include <string> 10 #include <string>
11 11
12 #include "src/v8.h" 12 #include "src/v8.h"
13 13
14 #include "src/asmjs/asm-types.h" 14 #include "src/asmjs/asm-types.h"
15 #include "src/ast/ast.h" 15 #include "src/ast/ast.h"
16 #include "src/ast/scopes.h" 16 #include "src/ast/scopes.h"
17 #include "src/base/bits.h" 17 #include "src/base/bits.h"
18 #include "src/codegen.h" 18 #include "src/codegen.h"
19 #include "src/globals.h" 19 #include "src/globals.h"
20 #include "src/utils.h" 20 #include "src/utils.h"
21 21
22 #define FAIL_LINE(line, msg) \
23 do { \
24 base::OS::SNPrintF(error_message_, sizeof(error_message_), \
25 "asm: line %d: %s", (line) + 1, msg); \
26 return AsmType::None(); \
27 } while (false)
28
22 #define FAIL(node, msg) \ 29 #define FAIL(node, msg) \
23 do { \ 30 do { \
24 int line = node->position() == kNoSourcePosition \ 31 int line = node->position() == kNoSourcePosition \
25 ? -1 \ 32 ? -1 \
26 : script_->GetLineNumber(node->position()); \ 33 : script_->GetLineNumber(node->position()); \
27 base::OS::SNPrintF(error_message_, sizeof(error_message_), \ 34 FAIL_LINE(line, msg); \
28 "asm: line %d: %s", line + 1, msg); \
29 return AsmType::None(); \
30 } while (false) 35 } while (false)
31 36
32 #define RECURSE(call) \ 37 #define RECURSE(call) \
33 do { \ 38 do { \
34 if (GetCurrentStackPosition() < stack_limit_) { \ 39 if (GetCurrentStackPosition() < stack_limit_) { \
35 stack_overflow_ = true; \ 40 stack_overflow_ = true; \
36 FAIL(root_, "Stack overflow while parsing asm.js module."); \ 41 FAIL(root_, "Stack overflow while parsing asm.js module."); \
37 } \ 42 } \
38 \ 43 \
39 AsmType* result = (call); \ 44 AsmType* result = (call); \
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 context_stack_.emplace_back( 89 context_stack_.emplace_back(
85 Context(current_statement->AsBlock()->statements())); 90 Context(current_statement->AsBlock()->statements()));
86 continue; 91 continue;
87 } 92 }
88 93
89 return current_statement; 94 return current_statement;
90 } 95 }
91 } 96 }
92 97
93 // ---------------------------------------------------------------------------- 98 // ----------------------------------------------------------------------------
99 // Implementation of AsmTyper::SourceLayoutTracker
100
101 bool AsmTyper::SourceLayoutTracker::IsValid() const {
102 const Section* kAllSections[] = {&use_asm_, &globals_, &functions_, &tables_,
103 &exports_};
104 for (size_t ii = 0; ii < arraysize(kAllSections); ++ii) {
105 const auto& curr_section = *kAllSections[ii];
106 for (size_t jj = ii + 1; jj < arraysize(kAllSections); ++jj) {
107 if (curr_section.IsPrecededBy(*kAllSections[jj])) {
108 return false;
109 }
110 }
111 }
112 return true;
113 }
114
115 void AsmTyper::SourceLayoutTracker::Section::AddNewElement(
116 const AstNode& node) {
117 const int node_pos = node.position();
118 if (start_ == kNoSourcePosition) {
119 start_ = node_pos;
120 } else {
121 start_ = std::min(start_, node_pos);
122 }
123 if (end_ == kNoSourcePosition) {
124 end_ = node_pos;
125 } else {
126 end_ = std::max(end_, node_pos);
127 }
128 }
129
130 bool AsmTyper::SourceLayoutTracker::Section::IsPrecededBy(
131 const Section& other) const {
132 if (start_ == kNoSourcePosition) {
133 DCHECK_EQ(end_, kNoSourcePosition);
134 return false;
135 }
136 if (other.start_ == kNoSourcePosition) {
137 DCHECK_EQ(other.end_, kNoSourcePosition);
138 return false;
139 }
140 DCHECK_LE(start_, end_);
141 DCHECK_LE(other.start_, other.end_);
142 return other.start_ <= end_;
143 }
144
145 // ----------------------------------------------------------------------------
94 // Implementation of AsmTyper::VariableInfo 146 // Implementation of AsmTyper::VariableInfo
95 147
96 AsmTyper::VariableInfo* AsmTyper::VariableInfo::ForSpecialSymbol( 148 AsmTyper::VariableInfo* AsmTyper::VariableInfo::ForSpecialSymbol(
97 Zone* zone, StandardMember standard_member) { 149 Zone* zone, StandardMember standard_member) {
98 DCHECK(standard_member == kStdlib || standard_member == kFFI || 150 DCHECK(standard_member == kStdlib || standard_member == kFFI ||
99 standard_member == kHeap || standard_member == kModule); 151 standard_member == kHeap || standard_member == kModule);
100 auto* new_var_info = new (zone) VariableInfo(AsmType::None()); 152 auto* new_var_info = new (zone) VariableInfo(AsmType::None());
101 new_var_info->standard_member_ = standard_member; 153 new_var_info->standard_member_ = standard_member;
102 new_var_info->mutability_ = kImmutableGlobal; 154 new_var_info->mutability_ = kImmutableGlobal;
103 return new_var_info; 155 return new_var_info;
104 } 156 }
105 157
106 AsmTyper::VariableInfo* AsmTyper::VariableInfo::Clone(Zone* zone) const { 158 AsmTyper::VariableInfo* AsmTyper::VariableInfo::Clone(Zone* zone) const {
107 CHECK(standard_member_ != kNone); 159 CHECK(standard_member_ != kNone);
108 CHECK(!type_->IsA(AsmType::None())); 160 CHECK(!type_->IsA(AsmType::None()));
109 auto* new_var_info = new (zone) VariableInfo(type_); 161 auto* new_var_info = new (zone) VariableInfo(type_);
110 new_var_info->standard_member_ = standard_member_; 162 new_var_info->standard_member_ = standard_member_;
111 new_var_info->mutability_ = mutability_; 163 new_var_info->mutability_ = mutability_;
112 return new_var_info; 164 return new_var_info;
113 } 165 }
114 166
115 void AsmTyper::VariableInfo::FirstForwardUseIs(VariableProxy* var) { 167 void AsmTyper::VariableInfo::SetFirstForwardUse(int source_location) {
116 DCHECK(first_forward_use_ == nullptr); 168 DCHECK(source_location_ == -1);
117 missing_definition_ = true; 169 missing_definition_ = true;
118 first_forward_use_ = var; 170 source_location_ = source_location;
119 } 171 }
120 172
121 // ---------------------------------------------------------------------------- 173 // ----------------------------------------------------------------------------
122 // Implementation of AsmTyper 174 // Implementation of AsmTyper
123 175
124 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, 176 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
125 FunctionLiteral* root) 177 FunctionLiteral* root)
126 : isolate_(isolate), 178 : isolate_(isolate),
127 zone_(zone), 179 zone_(zone),
128 script_(script), 180 script_(script),
129 root_(root), 181 root_(root),
130 forward_definitions_(zone), 182 forward_definitions_(zone),
131 ffi_use_signatures_(zone), 183 ffi_use_signatures_(zone),
132 stdlib_types_(zone), 184 stdlib_types_(zone),
133 stdlib_math_types_(zone), 185 stdlib_math_types_(zone),
134 module_info_(VariableInfo::ForSpecialSymbol(zone_, kModule)), 186 module_info_(VariableInfo::ForSpecialSymbol(zone_, kModule)),
135 global_scope_(ZoneHashMap::kDefaultHashMapCapacity, 187 global_scope_(ZoneHashMap::kDefaultHashMapCapacity,
136 ZoneAllocationPolicy(zone)), 188 ZoneAllocationPolicy(zone)),
137 local_scope_(ZoneHashMap::kDefaultHashMapCapacity, 189 local_scope_(ZoneHashMap::kDefaultHashMapCapacity,
138 ZoneAllocationPolicy(zone)), 190 ZoneAllocationPolicy(zone)),
139 stack_limit_(isolate->stack_guard()->real_climit()), 191 stack_limit_(isolate->stack_guard()->real_climit()),
140 node_types_(zone_), 192 module_node_types_(zone_),
193 function_node_types_(zone_),
141 fround_type_(AsmType::FroundType(zone_)), 194 fround_type_(AsmType::FroundType(zone_)),
142 ffi_type_(AsmType::FFIType(zone_)) { 195 ffi_type_(AsmType::FFIType(zone_)),
196 function_pointer_tables_(zone_) {
143 InitializeStdlib(); 197 InitializeStdlib();
144 } 198 }
145 199
146 namespace { 200 namespace {
147 bool ValidAsmIdentifier(Handle<String> name) { 201 bool ValidAsmIdentifier(Handle<String> name) {
148 static const char* kInvalidAsmNames[] = {"eval", "arguments"}; 202 static const char* kInvalidAsmNames[] = {"eval", "arguments"};
149 203
150 for (size_t ii = 0; ii < arraysize(kInvalidAsmNames); ++ii) { 204 for (size_t ii = 0; ii < arraysize(kInvalidAsmNames); ++ii) {
151 if (strcmp(name->ToCString().get(), kInvalidAsmNames[ii]) == 0) { 205 if (strcmp(name->ToCString().get(), kInvalidAsmNames[ii]) == 0) {
152 return false; 206 return false;
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 392
339 if (entry == nullptr && !module_name_.is_null() && 393 if (entry == nullptr && !module_name_.is_null() &&
340 module_name_->Equals(*variable->name())) { 394 module_name_->Equals(*variable->name())) {
341 return module_info_; 395 return module_info_;
342 } 396 }
343 397
344 return entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr; 398 return entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr;
345 } 399 }
346 400
347 void AsmTyper::AddForwardReference(VariableProxy* proxy, VariableInfo* info) { 401 void AsmTyper::AddForwardReference(VariableProxy* proxy, VariableInfo* info) {
348 info->FirstForwardUseIs(proxy); 402 info->SetFirstForwardUse(proxy->position() == kNoSourcePosition
403 ? -1
404 : script_->GetLineNumber(proxy->position()));
349 forward_definitions_.push_back(info); 405 forward_definitions_.push_back(info);
350 } 406 }
351 407
352 bool AsmTyper::AddGlobal(Variable* variable, VariableInfo* info) { 408 bool AsmTyper::AddGlobal(Variable* variable, VariableInfo* info) {
353 // We can't DCHECK(!in_function_) because function may actually install global 409 // We can't DCHECK(!in_function_) because function may actually install global
354 // names (forward defined functions and function tables.) 410 // names (forward defined functions and function tables.)
355 DCHECK(info->mutability() != VariableInfo::kInvalidMutability); 411 DCHECK(info->mutability() != VariableInfo::kInvalidMutability);
356 DCHECK(info->IsGlobal()); 412 DCHECK(info->IsGlobal());
357 DCHECK(ValidAsmIdentifier(variable->name())); 413 DCHECK(ValidAsmIdentifier(variable->name()));
358 414
(...skipping 24 matching lines...) Expand all
383 if (entry->value != nullptr) { 439 if (entry->value != nullptr) {
384 return false; 440 return false;
385 } 441 }
386 442
387 entry->value = info; 443 entry->value = info;
388 return true; 444 return true;
389 } 445 }
390 446
391 void AsmTyper::SetTypeOf(AstNode* node, AsmType* type) { 447 void AsmTyper::SetTypeOf(AstNode* node, AsmType* type) {
392 DCHECK_NE(type, AsmType::None()); 448 DCHECK_NE(type, AsmType::None());
393 DCHECK(node_types_.find(node) == node_types_.end()); 449 if (in_function_) {
394 node_types_.insert(std::make_pair(node, type)); 450 DCHECK(function_node_types_.find(node) == function_node_types_.end());
451 function_node_types_.insert(std::make_pair(node, type));
452 } else {
453 DCHECK(module_node_types_.find(node) == module_node_types_.end());
454 module_node_types_.insert(std::make_pair(node, type));
455 }
395 } 456 }
396 457
397 AsmType* AsmTyper::TypeOf(AstNode* node) const { 458 AsmType* AsmTyper::TypeOf(AstNode* node) const {
398 auto node_type_iter = node_types_.find(node); 459 auto node_type_iter = function_node_types_.find(node);
399 if (node_type_iter != node_types_.end()) { 460 if (node_type_iter != function_node_types_.end()) {
461 return node_type_iter->second;
462 }
463 node_type_iter = module_node_types_.find(node);
464 if (node_type_iter != module_node_types_.end()) {
400 return node_type_iter->second; 465 return node_type_iter->second;
401 } 466 }
402 467
403 // Sometimes literal nodes are not added to the node_type_ map simply because 468 // Sometimes literal nodes are not added to the node_type_ map simply because
404 // their are not visited with ValidateExpression(). 469 // their are not visited with ValidateExpression().
405 if (auto* literal = node->AsLiteral()) { 470 if (auto* literal = node->AsLiteral()) {
406 if (literal->raw_value()->ContainsDot()) { 471 if (literal->raw_value()->ContainsDot()) {
407 return AsmType::Double(); 472 return AsmType::Double();
408 } 473 }
409 uint32_t u; 474 uint32_t u;
(...skipping 17 matching lines...) Expand all
427 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(Variable* var) { 492 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(Variable* var) {
428 auto* var_info = Lookup(var); 493 auto* var_info = Lookup(var);
429 if (var_info == nullptr) { 494 if (var_info == nullptr) {
430 return kNone; 495 return kNone;
431 } 496 }
432 StandardMember member = var_info->standard_member(); 497 StandardMember member = var_info->standard_member();
433 return member; 498 return member;
434 } 499 }
435 500
436 bool AsmTyper::Validate() { 501 bool AsmTyper::Validate() {
437 if (!AsmType::None()->IsExactly(ValidateModule(root_))) { 502 return ValidateBeforeFunctionsPhase() &&
503 !AsmType::None()->IsExactly(ValidateModuleFunctions(root_)) &&
504 ValidateAfterFunctionsPhase();
505 }
506
507 bool AsmTyper::ValidateBeforeFunctionsPhase() {
508 if (!AsmType::None()->IsExactly(ValidateModuleBeforeFunctionsPhase(root_))) {
438 return true; 509 return true;
439 } 510 }
440 return false; 511 return false;
441 } 512 }
442 513
514 bool AsmTyper::ValidateInnerFunction(FunctionDeclaration* fun_decl) {
515 if (!AsmType::None()->IsExactly(ValidateModuleFunction(fun_decl))) {
516 return true;
517 }
518 return false;
519 }
520
521 bool AsmTyper::ValidateAfterFunctionsPhase() {
522 if (!AsmType::None()->IsExactly(ValidateModuleAfterFunctionsPhase(root_))) {
523 return true;
524 }
525 return false;
526 }
527
528 void AsmTyper::ClearFunctionNodeTypes() { function_node_types_.clear(); }
529
443 namespace { 530 namespace {
444 bool IsUseAsmDirective(Statement* first_statement) { 531 bool IsUseAsmDirective(Statement* first_statement) {
445 ExpressionStatement* use_asm = first_statement->AsExpressionStatement(); 532 ExpressionStatement* use_asm = first_statement->AsExpressionStatement();
446 if (use_asm == nullptr) { 533 if (use_asm == nullptr) {
447 return false; 534 return false;
448 } 535 }
449 536
450 Literal* use_asm_literal = use_asm->expression()->AsLiteral(); 537 Literal* use_asm_literal = use_asm->expression()->AsLiteral();
451 538
452 if (use_asm_literal == nullptr) { 539 if (use_asm_literal == nullptr) {
(...skipping 17 matching lines...) Expand all
470 if (assign->op() != Token::INIT) { 557 if (assign->op() != Token::INIT) {
471 // Done with initializers. 558 // Done with initializers.
472 return nullptr; 559 return nullptr;
473 } 560 }
474 return assign; 561 return assign;
475 } 562 }
476 563
477 } // namespace 564 } // namespace
478 565
479 // 6.1 ValidateModule 566 // 6.1 ValidateModule
480 namespace { 567 AsmType* AsmTyper::ValidateModuleBeforeFunctionsPhase(FunctionLiteral* fun) {
481 // SourceLayoutTracker keeps track of the start and end positions of each
482 // section in the asm.js source. The sections should not overlap, otherwise the
483 // asm.js source is invalid.
484 class SourceLayoutTracker {
485 public:
486 SourceLayoutTracker() = default;
487
488 bool IsValid() const {
489 const Section* kAllSections[] = {&use_asm_, &globals_, &functions_,
490 &tables_, &exports_};
491 for (size_t ii = 0; ii < arraysize(kAllSections); ++ii) {
492 const auto& curr_section = *kAllSections[ii];
493 for (size_t jj = ii + 1; jj < arraysize(kAllSections); ++jj) {
494 if (curr_section.OverlapsWith(*kAllSections[jj])) {
495 return false;
496 }
497 }
498 }
499 return true;
500 }
501
502 void AddUseAsm(const AstNode& node) { use_asm_.AddNewElement(node); }
503
504 void AddGlobal(const AstNode& node) { globals_.AddNewElement(node); }
505
506 void AddFunction(const AstNode& node) { functions_.AddNewElement(node); }
507
508 void AddTable(const AstNode& node) { tables_.AddNewElement(node); }
509
510 void AddExport(const AstNode& node) { exports_.AddNewElement(node); }
511
512 private:
513 class Section {
514 public:
515 Section() = default;
516 Section(const Section&) = default;
517 Section& operator=(const Section&) = default;
518
519 void AddNewElement(const AstNode& node) {
520 const int node_pos = node.position();
521 if (start_ == kNoSourcePosition) {
522 start_ = node_pos;
523 } else {
524 start_ = std::max(start_, node_pos);
525 }
526 if (end_ == kNoSourcePosition) {
527 end_ = node_pos;
528 } else {
529 end_ = std::max(end_, node_pos);
530 }
531 }
532
533 bool OverlapsWith(const Section& other) const {
534 if (start_ == kNoSourcePosition) {
535 DCHECK_EQ(end_, kNoSourcePosition);
536 return false;
537 }
538 if (other.start_ == kNoSourcePosition) {
539 DCHECK_EQ(other.end_, kNoSourcePosition);
540 return false;
541 }
542 return other.start_ < end_ || other.end_ < start_;
543 }
544
545 private:
546 int start_ = kNoSourcePosition;
547 int end_ = kNoSourcePosition;
548 };
549
550 Section use_asm_;
551 Section globals_;
552 Section functions_;
553 Section tables_;
554 Section exports_;
555
556 DISALLOW_COPY_AND_ASSIGN(SourceLayoutTracker);
557 };
558 } // namespace
559
560 AsmType* AsmTyper::ValidateModule(FunctionLiteral* fun) {
561 SourceLayoutTracker source_layout;
562
563 DeclarationScope* scope = fun->scope(); 568 DeclarationScope* scope = fun->scope();
564 if (!scope->is_function_scope()) FAIL(fun, "Not at function scope."); 569 if (!scope->is_function_scope()) FAIL(fun, "Not at function scope.");
565 if (!ValidAsmIdentifier(fun->name())) 570 if (!ValidAsmIdentifier(fun->name()))
566 FAIL(fun, "Invalid asm.js identifier in module name."); 571 FAIL(fun, "Invalid asm.js identifier in module name.");
567 module_name_ = fun->name(); 572 module_name_ = fun->name();
568 573
569 // Allowed parameters: Stdlib, FFI, Mem 574 // Allowed parameters: Stdlib, FFI, Mem
570 static const int MaxModuleParameters = 3; 575 static const int MaxModuleParameters = 3;
571 if (scope->num_parameters() > MaxModuleParameters) { 576 if (scope->num_parameters() > MaxModuleParameters) {
572 FAIL(fun, "asm.js modules may not have more than three parameters."); 577 FAIL(fun, "asm.js modules may not have more than three parameters.");
(...skipping 14 matching lines...) Expand all
587 } 592 }
588 593
589 auto* param_info = VariableInfo::ForSpecialSymbol( 594 auto* param_info = VariableInfo::ForSpecialSymbol(
590 zone_, kModuleParamInfo[ii].standard_member); 595 zone_, kModuleParamInfo[ii].standard_member);
591 596
592 if (!AddGlobal(param, param_info)) { 597 if (!AddGlobal(param, param_info)) {
593 FAIL(fun, "Redeclared identifier in module parameter."); 598 FAIL(fun, "Redeclared identifier in module parameter.");
594 } 599 }
595 } 600 }
596 601
597 ZoneVector<Assignment*> function_pointer_tables(zone_);
598 FlattenedStatements iter(zone_, fun->body()); 602 FlattenedStatements iter(zone_, fun->body());
599 auto* use_asm_directive = iter.Next(); 603 auto* use_asm_directive = iter.Next();
600 if (use_asm_directive == nullptr) { 604 if (use_asm_directive == nullptr) {
601 FAIL(fun, "Missing \"use asm\"."); 605 FAIL(fun, "Missing \"use asm\".");
602 } 606 }
603 // Check for extra assignment inserted by the parser when in this form: 607 // Check for extra assignment inserted by the parser when in this form:
604 // (function Module(a, b, c) {... }) 608 // (function Module(a, b, c) {... })
605 ExpressionStatement* estatement = use_asm_directive->AsExpressionStatement(); 609 ExpressionStatement* estatement = use_asm_directive->AsExpressionStatement();
606 if (estatement != nullptr) { 610 if (estatement != nullptr) {
607 Assignment* assignment = estatement->expression()->AsAssignment(); 611 Assignment* assignment = estatement->expression()->AsAssignment();
608 if (assignment != nullptr && assignment->target()->IsVariableProxy() && 612 if (assignment != nullptr && assignment->target()->IsVariableProxy() &&
609 assignment->target() 613 assignment->target()
610 ->AsVariableProxy() 614 ->AsVariableProxy()
611 ->var() 615 ->var()
612 ->is_sloppy_function_name()) { 616 ->is_sloppy_function_name()) {
613 use_asm_directive = iter.Next(); 617 use_asm_directive = iter.Next();
614 } 618 }
615 } 619 }
616 if (!IsUseAsmDirective(use_asm_directive)) { 620 if (!IsUseAsmDirective(use_asm_directive)) {
617 FAIL(fun, "Missing \"use asm\"."); 621 FAIL(fun, "Missing \"use asm\".");
618 } 622 }
619 source_layout.AddUseAsm(*use_asm_directive); 623 source_layout_.AddUseAsm(*use_asm_directive);
620 ReturnStatement* module_return = nullptr; 624 module_return_ = nullptr;
621 625
622 // *VIOLATION* The spec states that globals should be followed by function 626 // *VIOLATION* The spec states that globals should be followed by function
623 // declarations, which should be followed by function pointer tables, followed 627 // declarations, which should be followed by function pointer tables, followed
624 // by the module export (return) statement. Our AST might be rearraged by the 628 // by the module export (return) statement. Our AST might be rearraged by the
625 // parser, so we can't rely on it being in source code order. 629 // parser, so we can't rely on it being in source code order.
626 while (Statement* current = iter.Next()) { 630 while (Statement* current = iter.Next()) {
627 if (auto* assign = ExtractInitializerExpression(current)) { 631 if (auto* assign = ExtractInitializerExpression(current)) {
628 if (assign->value()->IsArrayLiteral()) { 632 if (assign->value()->IsArrayLiteral()) {
629 // Save function tables for later validation. 633 // Save function tables for later validation.
630 function_pointer_tables.push_back(assign); 634 function_pointer_tables_.push_back(assign);
631 } else { 635 } else {
632 RECURSE(ValidateGlobalDeclaration(assign)); 636 RECURSE(ValidateGlobalDeclaration(assign));
633 source_layout.AddGlobal(*assign); 637 source_layout_.AddGlobal(*assign);
634 } 638 }
635 continue; 639 continue;
636 } 640 }
637 641
638 if (auto* current_as_return = current->AsReturnStatement()) { 642 if (auto* current_as_return = current->AsReturnStatement()) {
639 if (module_return != nullptr) { 643 if (module_return_ != nullptr) {
640 FAIL(fun, "Multiple export statements."); 644 FAIL(fun, "Multiple export statements.");
641 } 645 }
642 module_return = current_as_return; 646 module_return_ = current_as_return;
643 source_layout.AddExport(*module_return); 647 source_layout_.AddExport(*module_return_);
644 continue; 648 continue;
645 } 649 }
646 650
647 FAIL(current, "Invalid top-level statement in asm.js module."); 651 FAIL(current, "Invalid top-level statement in asm.js module.");
648 } 652 }
649 653
654 return AsmType::Int(); // Any type that is not AsmType::None();
655 }
656
657 AsmType* AsmTyper::ValidateModuleFunction(FunctionDeclaration* fun_decl) {
658 RECURSE(ValidateFunction(fun_decl));
659 source_layout_.AddFunction(*fun_decl);
660
661 return AsmType::Int(); // Any type that is not AsmType::None();
662 }
663
664 AsmType* AsmTyper::ValidateModuleFunctions(FunctionLiteral* fun) {
665 DeclarationScope* scope = fun->scope();
650 Declaration::List* decls = scope->declarations(); 666 Declaration::List* decls = scope->declarations();
651 for (Declaration* decl : *decls) { 667 for (Declaration* decl : *decls) {
652 if (FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration()) { 668 if (FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration()) {
653 RECURSE(ValidateFunction(fun_decl)); 669 RECURSE(ValidateModuleFunction(fun_decl));
654 source_layout.AddFunction(*fun_decl);
655 continue; 670 continue;
656 } 671 }
657 } 672 }
658 673
659 for (auto* function_table : function_pointer_tables) { 674 return AsmType::Int(); // Any type that is not AsmType::None();
675 }
676
677 AsmType* AsmTyper::ValidateModuleAfterFunctionsPhase(FunctionLiteral* fun) {
678 for (auto* function_table : function_pointer_tables_) {
660 RECURSE(ValidateFunctionTable(function_table)); 679 RECURSE(ValidateFunctionTable(function_table));
661 source_layout.AddTable(*function_table); 680 source_layout_.AddTable(*function_table);
662 } 681 }
663 682
683 DeclarationScope* scope = fun->scope();
684 Declaration::List* decls = scope->declarations();
664 for (Declaration* decl : *decls) { 685 for (Declaration* decl : *decls) {
665 if (decl->IsFunctionDeclaration()) { 686 if (decl->IsFunctionDeclaration()) {
666 continue; 687 continue;
667 } 688 }
668 689
669 VariableDeclaration* var_decl = decl->AsVariableDeclaration(); 690 VariableDeclaration* var_decl = decl->AsVariableDeclaration();
670 if (var_decl == nullptr) { 691 if (var_decl == nullptr) {
671 FAIL(decl, "Invalid asm.js declaration."); 692 FAIL(decl, "Invalid asm.js declaration.");
672 } 693 }
673 694
674 auto* var_proxy = var_decl->proxy(); 695 auto* var_proxy = var_decl->proxy();
675 if (var_proxy == nullptr) { 696 if (var_proxy == nullptr) {
676 FAIL(decl, "Invalid asm.js declaration."); 697 FAIL(decl, "Invalid asm.js declaration.");
677 } 698 }
678 699
679 if (Lookup(var_proxy->var()) == nullptr) { 700 if (Lookup(var_proxy->var()) == nullptr) {
680 FAIL(decl, "Global variable missing initializer in asm.js module."); 701 FAIL(decl, "Global variable missing initializer in asm.js module.");
681 } 702 }
682 } 703 }
683 704
684 // 6.2 ValidateExport 705 // 6.2 ValidateExport
685 if (module_return == nullptr) { 706 if (module_return_ == nullptr) {
686 FAIL(fun, "Missing asm.js module export."); 707 FAIL(fun, "Missing asm.js module export.");
687 } 708 }
688 709
689 for (auto* forward_def : forward_definitions_) { 710 for (auto* forward_def : forward_definitions_) {
690 if (forward_def->missing_definition()) { 711 if (forward_def->missing_definition()) {
691 FAIL(forward_def->first_forward_use(), 712 FAIL_LINE(forward_def->source_location(),
692 "Missing definition for forward declared identifier."); 713 "Missing definition for forward declared identifier.");
693 } 714 }
694 } 715 }
695 716
696 RECURSE(ValidateExport(module_return)); 717 RECURSE(ValidateExport(module_return_));
697 718
698 if (!source_layout.IsValid()) { 719 if (!source_layout_.IsValid()) {
699 FAIL(fun, "Invalid asm.js source code layout."); 720 FAIL(fun, "Invalid asm.js source code layout.");
700 } 721 }
701 722
702 return AsmType::Int(); // Any type that is not AsmType::None(); 723 return AsmType::Int(); // Any type that is not AsmType::None();
703 } 724 }
704 725
705 namespace { 726 namespace {
706 bool IsDoubleAnnotation(BinaryOperation* binop) { 727 bool IsDoubleAnnotation(BinaryOperation* binop) {
707 // *VIOLATION* The parser replaces uses of +x with x*1.0. 728 // *VIOLATION* The parser replaces uses of +x with x*1.0.
708 if (binop->op() != Token::MUL) { 729 if (binop->op() != Token::MUL) {
(...skipping 2148 matching lines...) Expand 10 before | Expand all | Expand 10 after
2857 return true; 2878 return true;
2858 } 2879 }
2859 2880
2860 *error_message = typer.error_message(); 2881 *error_message = typer.error_message();
2861 return false; 2882 return false;
2862 } 2883 }
2863 2884
2864 } // namespace wasm 2885 } // namespace wasm
2865 } // namespace internal 2886 } // namespace internal
2866 } // namespace v8 2887 } // namespace v8
OLDNEW
« no previous file with comments | « src/asmjs/asm-typer.h ('k') | src/asmjs/asm-wasm-builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698