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

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

Powered by Google App Engine
This is Rietveld 408576698