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

Side by Side Diff: src/asmjs/asm-wasm-builder.cc

Issue 2134333003: V8. ASM-2-WASM. Migrates asm-wasm-builder to the new asm-typer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addresses comments. Created 4 years, 5 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
« no previous file with comments | « src/asmjs/asm-wasm-builder.h ('k') | src/flag-definitions.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 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/v8.h" 5 #include "src/v8.h"
6 6
7 // Required to get M_E etc. in MSVC. 7 // Required to get M_E etc. in MSVC.
8 #if defined(_WIN32) 8 #if defined(_WIN32)
9 #define _USE_MATH_DEFINES 9 #define _USE_MATH_DEFINES
10 #endif 10 #endif
11 #include <math.h> 11 #include <math.h>
12 12
13 #include "src/asmjs/asm-types.h"
13 #include "src/asmjs/asm-wasm-builder.h" 14 #include "src/asmjs/asm-wasm-builder.h"
14 #include "src/wasm/switch-logic.h" 15 #include "src/wasm/switch-logic.h"
15 #include "src/wasm/wasm-macro-gen.h" 16 #include "src/wasm/wasm-macro-gen.h"
16 #include "src/wasm/wasm-opcodes.h" 17 #include "src/wasm/wasm-opcodes.h"
17 18
18 #include "src/ast/ast.h" 19 #include "src/ast/ast.h"
19 #include "src/ast/scopes.h" 20 #include "src/ast/scopes.h"
20 #include "src/codegen.h" 21 #include "src/codegen.h"
21 #include "src/type-cache.h"
22 22
23 namespace v8 { 23 namespace v8 {
24 namespace internal { 24 namespace internal {
25 namespace wasm { 25 namespace wasm {
26 26
27 #define RECURSE(call) \ 27 #define RECURSE(call) \
28 do { \ 28 do { \
29 DCHECK(!HasStackOverflow()); \ 29 DCHECK(!HasStackOverflow()); \
30 call; \ 30 call; \
31 if (HasStackOverflow()) return; \ 31 if (HasStackOverflow()) return; \
(...skipping 20 matching lines...) Expand all
52 global_variables_(base::HashMap::PointersMatch, 52 global_variables_(base::HashMap::PointersMatch,
53 ZoneHashMap::kDefaultHashMapCapacity, 53 ZoneHashMap::kDefaultHashMapCapacity,
54 ZoneAllocationPolicy(zone)), 54 ZoneAllocationPolicy(zone)),
55 scope_(kModuleScope), 55 scope_(kModuleScope),
56 builder_(new (zone) WasmModuleBuilder(zone)), 56 builder_(new (zone) WasmModuleBuilder(zone)),
57 current_function_builder_(nullptr), 57 current_function_builder_(nullptr),
58 literal_(literal), 58 literal_(literal),
59 isolate_(isolate), 59 isolate_(isolate),
60 zone_(zone), 60 zone_(zone),
61 typer_(typer), 61 typer_(typer),
62 cache_(TypeCache::Get()),
63 breakable_blocks_(zone), 62 breakable_blocks_(zone),
64 foreign_variables_(zone), 63 foreign_variables_(zone),
65 init_function_index_(0), 64 init_function_index_(0),
66 foreign_init_function_index_(0), 65 foreign_init_function_index_(0),
67 next_table_index_(0), 66 next_table_index_(0),
68 function_tables_(base::HashMap::PointersMatch, 67 function_tables_(base::HashMap::PointersMatch,
69 ZoneHashMap::kDefaultHashMapCapacity, 68 ZoneHashMap::kDefaultHashMapCapacity,
70 ZoneAllocationPolicy(zone)), 69 ZoneAllocationPolicy(zone)),
71 imported_function_table_(this), 70 imported_function_table_(this) {
72 bounds_(typer->bounds()) {
73 InitializeAstVisitor(isolate); 71 InitializeAstVisitor(isolate);
74 } 72 }
75 73
76 void InitializeInitFunction() { 74 void InitializeInitFunction() {
77 init_function_index_ = builder_->AddFunction(); 75 init_function_index_ = builder_->AddFunction();
78 FunctionSig::Builder b(zone(), 0, 0); 76 FunctionSig::Builder b(zone(), 0, 0);
79 current_function_builder_ = builder_->FunctionAt(init_function_index_); 77 current_function_builder_ = builder_->FunctionAt(init_function_index_);
80 current_function_builder_->SetSignature(b.Build()); 78 current_function_builder_->SetSignature(b.Build());
81 builder_->MarkStartFunction(init_function_index_); 79 builder_->MarkStartFunction(init_function_index_);
82 current_function_builder_ = nullptr; 80 current_function_builder_ = nullptr;
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 ZoneVector<BlockVisitor*> blocks(zone_); 350 ZoneVector<BlockVisitor*> blocks(zone_);
353 ZoneVector<int32_t> cases(zone_); 351 ZoneVector<int32_t> cases(zone_);
354 ZoneMap<int, unsigned int> case_to_block(zone_); 352 ZoneMap<int, unsigned int> case_to_block(zone_);
355 bool has_default = false; 353 bool has_default = false;
356 for (int i = case_count - 1; i >= 0; i--) { 354 for (int i = case_count - 1; i >= 0; i--) {
357 CaseClause* clause = clauses->at(i); 355 CaseClause* clause = clauses->at(i);
358 blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false)); 356 blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false));
359 if (!clause->is_default()) { 357 if (!clause->is_default()) {
360 Literal* label = clause->label()->AsLiteral(); 358 Literal* label = clause->label()->AsLiteral();
361 Handle<Object> value = label->value(); 359 Handle<Object> value = label->value();
362 DCHECK(value->IsNumber() &&
363 bounds_->get(label).upper->Is(cache_.kAsmSigned));
364 int32_t label_value; 360 int32_t label_value;
365 if (!value->ToInt32(&label_value)) { 361 bool label_is_i32 = value->ToInt32(&label_value);
366 UNREACHABLE(); 362 DCHECK(value->IsNumber() && label_is_i32);
367 } 363 (void)label_is_i32;
368 case_to_block[label_value] = i; 364 case_to_block[label_value] = i;
369 cases.push_back(label_value); 365 cases.push_back(label_value);
370 } else { 366 } else {
371 DCHECK_EQ(i, case_count - 1); 367 DCHECK_EQ(i, case_count - 1);
372 has_default = true; 368 has_default = true;
373 } 369 }
374 } 370 }
375 if (!has_default || case_count > 1) { 371 if (!has_default || case_count > 1) {
376 int default_block = has_default ? case_count - 1 : case_count; 372 int default_block = has_default ? case_count - 1 : case_count;
377 BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false); 373 BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 UNREACHABLE(); 448 UNREACHABLE();
453 } 449 }
454 450
455 void VisitDebuggerStatement(DebuggerStatement* stmt) override { 451 void VisitDebuggerStatement(DebuggerStatement* stmt) override {
456 UNREACHABLE(); 452 UNREACHABLE();
457 } 453 }
458 454
459 void VisitFunctionLiteral(FunctionLiteral* expr) override { 455 void VisitFunctionLiteral(FunctionLiteral* expr) override {
460 Scope* scope = expr->scope(); 456 Scope* scope = expr->scope();
461 if (scope_ == kFuncScope) { 457 if (scope_ == kFuncScope) {
462 if (bounds_->get(expr).lower->IsFunction()) { 458 if (auto* func_type = typer_->TypeOf(expr)->AsFunctionType()) {
463 // Build the signature for the function. 459 // Build the signature for the function.
464 FunctionType* func_type = bounds_->get(expr).lower->AsFunction(); 460 LocalType return_type = TypeFrom(func_type->ReturnType());
465 LocalType return_type = TypeFrom(func_type->Result()); 461 const auto& arguments = func_type->Arguments();
466 FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1, 462 FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1,
467 func_type->Arity()); 463 arguments.size());
468 if (return_type != kAstStmt) b.AddReturn(return_type); 464 if (return_type != kAstStmt) b.AddReturn(return_type);
469 for (int i = 0; i < expr->parameter_count(); ++i) { 465 for (int i = 0; i < expr->parameter_count(); ++i) {
470 LocalType type = TypeFrom(func_type->Parameter(i)); 466 LocalType type = TypeFrom(arguments[i]);
471 DCHECK_NE(kAstStmt, type); 467 DCHECK_NE(kAstStmt, type);
472 b.AddParam(type); 468 b.AddParam(type);
473 InsertParameter(scope->parameter(i), type, i); 469 InsertParameter(scope->parameter(i), type, i);
474 } 470 }
475 current_function_builder_->SetSignature(b.Build()); 471 current_function_builder_->SetSignature(b.Build());
476 } else { 472 } else {
477 UNREACHABLE(); 473 UNREACHABLE();
478 } 474 }
479 } 475 }
480 RECURSE(VisitStatements(expr->body())); 476 RECURSE(VisitStatements(expr->body()));
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 LookupOrInsertLocal(var, var_type)); 562 LookupOrInsertLocal(var, var_type));
567 } 563 }
568 } 564 }
569 } 565 }
570 566
571 void VisitLiteral(Literal* expr) override { 567 void VisitLiteral(Literal* expr) override {
572 Handle<Object> value = expr->value(); 568 Handle<Object> value = expr->value();
573 if (!value->IsNumber() || (scope_ != kFuncScope && scope_ != kInitScope)) { 569 if (!value->IsNumber() || (scope_ != kFuncScope && scope_ != kInitScope)) {
574 return; 570 return;
575 } 571 }
576 Type* type = bounds_->get(expr).upper; 572 AsmType* type = typer_->TypeOf(expr);
577 if (type->Is(cache_.kAsmSigned)) { 573 DCHECK_NE(type, AsmType::None());
574
575 if (type->IsA(AsmType::Signed())) {
578 int32_t i = 0; 576 int32_t i = 0;
579 if (!value->ToInt32(&i)) { 577 if (!value->ToInt32(&i)) {
580 UNREACHABLE(); 578 UNREACHABLE();
581 } 579 }
582 byte code[] = {WASM_I32V(i)}; 580 byte code[] = {WASM_I32V(i)};
583 current_function_builder_->EmitCode(code, sizeof(code)); 581 current_function_builder_->EmitCode(code, sizeof(code));
584 } else if (type->Is(cache_.kAsmUnsigned) || type->Is(cache_.kAsmFixnum)) { 582 } else if (type->IsA(AsmType::Unsigned()) || type->IsA(AsmType::FixNum())) {
585 uint32_t u = 0; 583 uint32_t u = 0;
586 if (!value->ToUint32(&u)) { 584 if (!value->ToUint32(&u)) {
587 UNREACHABLE(); 585 UNREACHABLE();
588 } 586 }
589 int32_t i = static_cast<int32_t>(u); 587 int32_t i = static_cast<int32_t>(u);
590 byte code[] = {WASM_I32V(i)}; 588 byte code[] = {WASM_I32V(i)};
591 current_function_builder_->EmitCode(code, sizeof(code)); 589 current_function_builder_->EmitCode(code, sizeof(code));
592 } else if (type->Is(cache_.kAsmDouble)) { 590 } else if (type->IsA(AsmType::Double())) {
593 double val = expr->raw_value()->AsNumber(); 591 double val = expr->raw_value()->AsNumber();
594 byte code[] = {WASM_F64(val)}; 592 byte code[] = {WASM_F64(val)};
595 current_function_builder_->EmitCode(code, sizeof(code)); 593 current_function_builder_->EmitCode(code, sizeof(code));
596 } else { 594 } else {
597 UNREACHABLE(); 595 UNREACHABLE();
598 } 596 }
599 } 597 }
600 598
601 void VisitRegExpLiteral(RegExpLiteral* expr) override { UNREACHABLE(); } 599 void VisitRegExpLiteral(RegExpLiteral* expr) override { UNREACHABLE(); }
602 600
(...skipping 25 matching lines...) Expand all
628 current_function_builder_ = builder_->FunctionAt(init_function_index_); 626 current_function_builder_ = builder_->FunctionAt(init_function_index_);
629 scope_ = kInitScope; 627 scope_ = kInitScope;
630 } 628 }
631 629
632 void UnLoadInitFunction() { 630 void UnLoadInitFunction() {
633 scope_ = kModuleScope; 631 scope_ = kModuleScope;
634 current_function_builder_ = nullptr; 632 current_function_builder_ = nullptr;
635 } 633 }
636 634
637 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { 635 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) {
638 FunctionType* func_type = 636 auto* func_tbl_type = typer_->TypeOf(funcs)->AsFunctionTableType();
639 bounds_->get(funcs).lower->AsArray()->Element()->AsFunction(); 637 DCHECK_NOT_NULL(func_tbl_type);
640 LocalType return_type = TypeFrom(func_type->Result()); 638 auto* func_type = func_tbl_type->signature()->AsFunctionType();
639 const auto& arguments = func_type->Arguments();
640 LocalType return_type = TypeFrom(func_type->ReturnType());
641 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, 641 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
642 func_type->Arity()); 642 arguments.size());
643 if (return_type != kAstStmt) { 643 if (return_type != kAstStmt) {
644 sig.AddReturn(static_cast<LocalType>(return_type)); 644 sig.AddReturn(return_type);
645 } 645 }
646 for (int i = 0; i < func_type->Arity(); ++i) { 646 for (auto* arg : arguments) {
647 sig.AddParam(TypeFrom(func_type->Parameter(i))); 647 sig.AddParam(TypeFrom(arg));
648 } 648 }
649 uint32_t signature_index = builder_->AddSignature(sig.Build()); 649 uint32_t signature_index = builder_->AddSignature(sig.Build());
650 InsertFunctionTable(table->var(), next_table_index_, signature_index); 650 InsertFunctionTable(table->var(), next_table_index_, signature_index);
651 next_table_index_ += funcs->values()->length(); 651 next_table_index_ += funcs->values()->length();
652 for (int i = 0; i < funcs->values()->length(); ++i) { 652 for (int i = 0; i < funcs->values()->length(); ++i) {
653 VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); 653 VariableProxy* func = funcs->values()->at(i)->AsVariableProxy();
654 DCHECK_NOT_NULL(func); 654 DCHECK_NOT_NULL(func);
655 builder_->AddIndirectFunction(LookupOrInsertFunction(func->var())); 655 builder_->AddIndirectFunction(LookupOrInsertFunction(func->var()));
656 } 656 }
657 } 657 }
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 } else { 798 } else {
799 current_function_builder_->EmitSetLocal( 799 current_function_builder_->EmitSetLocal(
800 LookupOrInsertLocal(var, var_type)); 800 LookupOrInsertLocal(var, var_type));
801 } 801 }
802 } 802 }
803 803
804 Property* target_prop = expr->target()->AsProperty(); 804 Property* target_prop = expr->target()->AsProperty();
805 if (target_prop != nullptr) { 805 if (target_prop != nullptr) {
806 // Left hand side is a property access, i.e. the asm.js heap. 806 // Left hand side is a property access, i.e. the asm.js heap.
807 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && 807 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() &&
808 bounds_->get(expr->target()->AsProperty()->obj()) 808 typer_->TypeOf(expr->target()->AsProperty()->obj())
809 .lower->Is(cache_.kFloat32Array)) { 809 ->IsA(AsmType::Float32Array())) {
810 current_function_builder_->Emit(kExprF32ConvertF64); 810 current_function_builder_->Emit(kExprF32ConvertF64);
811 } 811 }
812 WasmOpcode opcode; 812 WasmOpcode opcode;
813 if (type == MachineType::Int8()) { 813 if (type == MachineType::Int8()) {
814 opcode = kExprI32AsmjsStoreMem8; 814 opcode = kExprI32AsmjsStoreMem8;
815 } else if (type == MachineType::Uint8()) { 815 } else if (type == MachineType::Uint8()) {
816 opcode = kExprI32AsmjsStoreMem8; 816 opcode = kExprI32AsmjsStoreMem8;
817 } else if (type == MachineType::Int16()) { 817 } else if (type == MachineType::Int16()) {
818 opcode = kExprI32AsmjsStoreMem16; 818 opcode = kExprI32AsmjsStoreMem16;
819 } else if (type == MachineType::Uint16()) { 819 } else if (type == MachineType::Uint16()) {
(...skipping 19 matching lines...) Expand all
839 839
840 void VisitAssignment(Assignment* expr) override { 840 void VisitAssignment(Assignment* expr) override {
841 bool as_init = false; 841 bool as_init = false;
842 if (scope_ == kModuleScope) { 842 if (scope_ == kModuleScope) {
843 Property* prop = expr->value()->AsProperty(); 843 Property* prop = expr->value()->AsProperty();
844 if (prop != nullptr) { 844 if (prop != nullptr) {
845 VariableProxy* vp = prop->obj()->AsVariableProxy(); 845 VariableProxy* vp = prop->obj()->AsVariableProxy();
846 if (vp != nullptr && vp->var()->IsParameter() && 846 if (vp != nullptr && vp->var()->IsParameter() &&
847 vp->var()->index() == 1) { 847 vp->var()->index() == 1) {
848 VariableProxy* target = expr->target()->AsVariableProxy(); 848 VariableProxy* target = expr->target()->AsVariableProxy();
849 if (bounds_->get(target).lower->Is(Type::Function())) { 849 if (typer_->TypeOf(target)->AsFFIType() != nullptr) {
850 const AstRawString* name = 850 const AstRawString* name =
851 prop->key()->AsLiteral()->AsRawPropertyName(); 851 prop->key()->AsLiteral()->AsRawPropertyName();
852 imported_function_table_.AddImport( 852 imported_function_table_.AddImport(
853 target->var(), reinterpret_cast<const char*>(name->raw_data()), 853 target->var(), reinterpret_cast<const char*>(name->raw_data()),
854 name->length()); 854 name->length());
855 } 855 }
856 } 856 }
857 // Property values in module scope don't emit code, so return. 857 // Property values in module scope don't emit code, so return.
858 return; 858 return;
859 } 859 }
860 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); 860 ArrayLiteral* funcs = expr->value()->AsArrayLiteral();
861 if (funcs != nullptr && 861 if (funcs != nullptr &&
862 bounds_->get(funcs).lower->AsArray()->Element()->IsFunction()) { 862 typer_->TypeOf(funcs)
863 ->AsFunctionTableType()
864 ->signature()
865 ->AsFunctionType()) {
863 VariableProxy* target = expr->target()->AsVariableProxy(); 866 VariableProxy* target = expr->target()->AsVariableProxy();
864 DCHECK_NOT_NULL(target); 867 DCHECK_NOT_NULL(target);
865 AddFunctionTable(target, funcs); 868 AddFunctionTable(target, funcs);
866 // Only add to the function table. No init needed. 869 // Only add to the function table. No init needed.
867 return; 870 return;
868 } 871 }
869 if (expr->value()->IsCallNew()) { 872 if (expr->value()->IsCallNew()) {
870 // No init code to emit for CallNew nodes. 873 // No init code to emit for CallNew nodes.
871 return; 874 return;
872 } 875 }
(...skipping 25 matching lines...) Expand all
898 if (!key_literal->value().is_null()) { 901 if (!key_literal->value().is_null()) {
899 Handle<Name> name = 902 Handle<Name> name =
900 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked(); 903 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked();
901 LocalType type = is_float ? kAstF64 : kAstI32; 904 LocalType type = is_float ? kAstF64 : kAstI32;
902 foreign_variables_.push_back({name, var, type}); 905 foreign_variables_.push_back({name, var, type});
903 } 906 }
904 } 907 }
905 908
906 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { 909 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) {
907 Expression* obj = expr->obj(); 910 Expression* obj = expr->obj();
908 DCHECK_EQ(bounds_->get(obj).lower, bounds_->get(obj).upper); 911 AsmType* type = typer_->TypeOf(obj);
909 Type* type = bounds_->get(obj).lower;
910 int size; 912 int size;
911 if (type->Is(cache_.kUint8Array)) { 913 if (type->IsA(AsmType::Uint8Array())) {
912 *mtype = MachineType::Uint8(); 914 *mtype = MachineType::Uint8();
913 size = 1; 915 size = 1;
914 } else if (type->Is(cache_.kInt8Array)) { 916 } else if (type->IsA(AsmType::Int8Array())) {
915 *mtype = MachineType::Int8(); 917 *mtype = MachineType::Int8();
916 size = 1; 918 size = 1;
917 } else if (type->Is(cache_.kUint16Array)) { 919 } else if (type->IsA(AsmType::Uint16Array())) {
918 *mtype = MachineType::Uint16(); 920 *mtype = MachineType::Uint16();
919 size = 2; 921 size = 2;
920 } else if (type->Is(cache_.kInt16Array)) { 922 } else if (type->IsA(AsmType::Int16Array())) {
921 *mtype = MachineType::Int16(); 923 *mtype = MachineType::Int16();
922 size = 2; 924 size = 2;
923 } else if (type->Is(cache_.kUint32Array)) { 925 } else if (type->IsA(AsmType::Uint32Array())) {
924 *mtype = MachineType::Uint32(); 926 *mtype = MachineType::Uint32();
925 size = 4; 927 size = 4;
926 } else if (type->Is(cache_.kInt32Array)) { 928 } else if (type->IsA(AsmType::Int32Array())) {
927 *mtype = MachineType::Int32(); 929 *mtype = MachineType::Int32();
928 size = 4; 930 size = 4;
929 } else if (type->Is(cache_.kUint32Array)) { 931 } else if (type->IsA(AsmType::Uint32Array())) {
930 *mtype = MachineType::Uint32(); 932 *mtype = MachineType::Uint32();
931 size = 4; 933 size = 4;
932 } else if (type->Is(cache_.kFloat32Array)) { 934 } else if (type->IsA(AsmType::Float32Array())) {
933 *mtype = MachineType::Float32(); 935 *mtype = MachineType::Float32();
934 size = 4; 936 size = 4;
935 } else if (type->Is(cache_.kFloat64Array)) { 937 } else if (type->IsA(AsmType::Float64Array())) {
936 *mtype = MachineType::Float64(); 938 *mtype = MachineType::Float64();
937 size = 8; 939 size = 8;
938 } else { 940 } else {
939 UNREACHABLE(); 941 UNREACHABLE();
940 } 942 }
941 if (size == 1) { 943 if (size == 1) {
942 // Allow more general expression in byte arrays than the spec 944 // Allow more general expression in byte arrays than the spec
943 // strictly permits. 945 // strictly permits.
944 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in 946 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in
945 // places that strictly should be HEAP8[HEAP32[..]>>0]. 947 // places that strictly should be HEAP8[HEAP32[..]>>0].
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 if (literal != nullptr) { 1223 if (literal != nullptr) {
1222 // constant fold Math.fround(#const); 1224 // constant fold Math.fround(#const);
1223 if (literal->raw_value()->IsNumber()) { 1225 if (literal->raw_value()->IsNumber()) {
1224 float val = static_cast<float>(literal->raw_value()->AsNumber()); 1226 float val = static_cast<float>(literal->raw_value()->AsNumber());
1225 byte code[] = {WASM_F32(val)}; 1227 byte code[] = {WASM_F32(val)};
1226 current_function_builder_->EmitCode(code, sizeof(code)); 1228 current_function_builder_->EmitCode(code, sizeof(code));
1227 return true; 1229 return true;
1228 } 1230 }
1229 } 1231 }
1230 VisitCallArgs(call); 1232 VisitCallArgs(call);
1231 switch (TypeIndexOf(args->at(0))) { 1233 static const bool kDontIgnoreSign = false;
1234 switch (TypeIndexOf(args->at(0), kDontIgnoreSign)) {
1232 case kInt32: 1235 case kInt32:
1233 case kFixnum: 1236 case kFixnum:
1234 current_function_builder_->Emit(kExprF32SConvertI32); 1237 current_function_builder_->Emit(kExprF32SConvertI32);
1235 break; 1238 break;
1236 case kUint32: 1239 case kUint32:
1237 current_function_builder_->Emit(kExprF32UConvertI32); 1240 current_function_builder_->Emit(kExprF32UConvertI32);
1238 break; 1241 break;
1239 case kFloat32: 1242 case kFloat32:
1240 break; 1243 break;
1241 case kFloat64: 1244 case kFloat64:
(...skipping 26 matching lines...) Expand all
1268 case Call::OTHER_CALL: { 1271 case Call::OTHER_CALL: {
1269 DCHECK_EQ(kFuncScope, scope_); 1272 DCHECK_EQ(kFuncScope, scope_);
1270 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 1273 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1271 if (proxy != nullptr) { 1274 if (proxy != nullptr) {
1272 if (VisitStdlibFunction(expr, proxy)) { 1275 if (VisitStdlibFunction(expr, proxy)) {
1273 return; 1276 return;
1274 } 1277 }
1275 } 1278 }
1276 uint32_t index; 1279 uint32_t index;
1277 VariableProxy* vp = expr->expression()->AsVariableProxy(); 1280 VariableProxy* vp = expr->expression()->AsVariableProxy();
1278 if (vp != nullptr && 1281 DCHECK_NOT_NULL(vp);
1279 Type::Any()->Is(bounds_->get(vp).lower->AsFunction()->Result())) { 1282 if (typer_->TypeOf(vp)->AsFFIType() != nullptr) {
1280 LocalType return_type = TypeOf(expr); 1283 LocalType return_type = TypeOf(expr);
1281 ZoneList<Expression*>* args = expr->arguments(); 1284 ZoneList<Expression*>* args = expr->arguments();
1282 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, 1285 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
1283 args->length()); 1286 args->length());
1284 if (return_type != kAstStmt) { 1287 if (return_type != kAstStmt) {
1285 sig.AddReturn(return_type); 1288 sig.AddReturn(return_type);
1286 } 1289 }
1287 for (int i = 0; i < args->length(); ++i) { 1290 for (int i = 0; i < args->length(); ++i) {
1288 sig.AddParam(TypeOf(args->at(i))); 1291 sig.AddParam(TypeOf(args->at(i)));
1289 } 1292 }
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
1472 Expression* GetLeft(BinaryOperation* expr) { 1475 Expression* GetLeft(BinaryOperation* expr) {
1473 if (expr->op() == Token::BIT_XOR) { 1476 if (expr->op() == Token::BIT_XOR) {
1474 return expr->left()->AsBinaryOperation()->left(); 1477 return expr->left()->AsBinaryOperation()->left();
1475 } else { 1478 } else {
1476 return expr->left(); 1479 return expr->left();
1477 } 1480 }
1478 } 1481 }
1479 1482
1480 void VisitBinaryOperation(BinaryOperation* expr) override { 1483 void VisitBinaryOperation(BinaryOperation* expr) override {
1481 ConvertOperation convertOperation = MatchBinaryOperation(expr); 1484 ConvertOperation convertOperation = MatchBinaryOperation(expr);
1485 static const bool kDontIgnoreSign = false;
1482 if (convertOperation == kToDouble) { 1486 if (convertOperation == kToDouble) {
1483 RECURSE(Visit(expr->left())); 1487 RECURSE(Visit(expr->left()));
1484 TypeIndex type = TypeIndexOf(expr->left()); 1488 TypeIndex type = TypeIndexOf(expr->left(), kDontIgnoreSign);
1485 if (type == kInt32 || type == kFixnum) { 1489 if (type == kInt32 || type == kFixnum) {
1486 current_function_builder_->Emit(kExprF64SConvertI32); 1490 current_function_builder_->Emit(kExprF64SConvertI32);
1487 } else if (type == kUint32) { 1491 } else if (type == kUint32) {
1488 current_function_builder_->Emit(kExprF64UConvertI32); 1492 current_function_builder_->Emit(kExprF64UConvertI32);
1489 } else if (type == kFloat32) { 1493 } else if (type == kFloat32) {
1490 current_function_builder_->Emit(kExprF64ConvertF32); 1494 current_function_builder_->Emit(kExprF64ConvertF32);
1491 } else { 1495 } else {
1492 UNREACHABLE(); 1496 UNREACHABLE();
1493 } 1497 }
1494 } else if (convertOperation == kToInt) { 1498 } else if (convertOperation == kToInt) {
1495 RECURSE(Visit(GetLeft(expr))); 1499 RECURSE(Visit(GetLeft(expr)));
1496 TypeIndex type = TypeIndexOf(GetLeft(expr)); 1500 TypeIndex type = TypeIndexOf(GetLeft(expr), kDontIgnoreSign);
1497 if (type == kFloat32) { 1501 if (type == kFloat32) {
1498 current_function_builder_->Emit(kExprI32AsmjsSConvertF32); 1502 current_function_builder_->Emit(kExprI32AsmjsSConvertF32);
1499 } else if (type == kFloat64) { 1503 } else if (type == kFloat64) {
1500 current_function_builder_->Emit(kExprI32AsmjsSConvertF64); 1504 current_function_builder_->Emit(kExprI32AsmjsSConvertF64);
1501 } else { 1505 } else {
1502 UNREACHABLE(); 1506 UNREACHABLE();
1503 } 1507 }
1504 } else if (convertOperation == kAsIs) { 1508 } else if (convertOperation == kAsIs) {
1505 RECURSE(Visit(GetLeft(expr))); 1509 RECURSE(Visit(GetLeft(expr)));
1506 } else { 1510 } else {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1576 1580
1577 enum TypeIndex { 1581 enum TypeIndex {
1578 kInt32 = 0, 1582 kInt32 = 0,
1579 kUint32 = 1, 1583 kUint32 = 1,
1580 kFloat32 = 2, 1584 kFloat32 = 2,
1581 kFloat64 = 3, 1585 kFloat64 = 3,
1582 kFixnum = 4 1586 kFixnum = 4
1583 }; 1587 };
1584 1588
1585 TypeIndex TypeIndexOf(Expression* left, Expression* right, bool ignore_sign) { 1589 TypeIndex TypeIndexOf(Expression* left, Expression* right, bool ignore_sign) {
1586 TypeIndex left_index = TypeIndexOf(left); 1590 TypeIndex left_index = TypeIndexOf(left, ignore_sign);
1587 TypeIndex right_index = TypeIndexOf(right); 1591 TypeIndex right_index = TypeIndexOf(right, ignore_sign);
1588 if (left_index == kFixnum) { 1592 if (left_index == kFixnum) {
1589 left_index = right_index; 1593 left_index = right_index;
1590 } 1594 }
1591 if (right_index == kFixnum) { 1595 if (right_index == kFixnum) {
1592 right_index = left_index; 1596 right_index = left_index;
1593 } 1597 }
1594 if (left_index == kFixnum && right_index == kFixnum) { 1598 if (left_index == kFixnum && right_index == kFixnum) {
1595 left_index = kInt32; 1599 left_index = kInt32;
1596 right_index = kInt32; 1600 right_index = kInt32;
1597 } 1601 }
1598 DCHECK((left_index == right_index) || 1602 if (left_index != right_index) {
1599 (ignore_sign && (left_index <= 1) && (right_index <= 1))); 1603 DCHECK(ignore_sign && (left_index <= 1) && (right_index <= 1));
1604 }
1600 return left_index; 1605 return left_index;
1601 } 1606 }
1602 1607
1603 TypeIndex TypeIndexOf(Expression* expr) { 1608 TypeIndex TypeIndexOf(Expression* expr, bool ignore_sign) {
1604 DCHECK_EQ(bounds_->get(expr).lower, bounds_->get(expr).upper); 1609 AsmType* type = typer_->TypeOf(expr);
1605 Type* type = bounds_->get(expr).lower; 1610 if (type->IsA(AsmType::FixNum())) {
1606 if (type->Is(cache_.kAsmFixnum)) {
1607 return kFixnum; 1611 return kFixnum;
1608 } else if (type->Is(cache_.kAsmSigned)) { 1612 }
1609 return kInt32; 1613
1610 } else if (type->Is(cache_.kAsmUnsigned)) { 1614 if (type->IsA(AsmType::Signed())) {
1611 return kUint32;
1612 } else if (type->Is(cache_.kAsmInt)) {
1613 return kInt32;
1614 } else if (type->Is(cache_.kAsmFloat)) {
1615 return kFloat32;
1616 } else if (type->Is(cache_.kAsmDouble)) {
1617 return kFloat64;
1618 } else {
1619 UNREACHABLE();
1620 return kInt32; 1615 return kInt32;
1621 } 1616 }
1617
1618 if (type->IsA(AsmType::Unsigned())) {
1619 return kUint32;
1620 }
1621
1622 if (type->IsA(AsmType::Intish())) {
1623 if (!ignore_sign) {
1624 // TODO(jpp): log a warning and move on.
1625 }
1626 return kInt32;
1627 }
1628
1629 if (type->IsA(AsmType::Floatish())) {
1630 return kFloat32;
1631 }
1632
1633 if (type->IsA(AsmType::DoubleQ())) {
1634 return kFloat64;
1635 }
1636
1637 UNREACHABLE();
1638 return kInt32;
1622 } 1639 }
1623 1640
1624 #undef CASE 1641 #undef CASE
1625 #undef NON_SIGNED_INT 1642 #undef NON_SIGNED_INT
1626 #undef SIGNED 1643 #undef SIGNED
1627 #undef NON_SIGNED 1644 #undef NON_SIGNED
1628 1645
1629 void VisitThisFunction(ThisFunction* expr) override { UNREACHABLE(); } 1646 void VisitThisFunction(ThisFunction* expr) override { UNREACHABLE(); }
1630 1647
1631 void VisitDeclarations(ZoneList<Declaration*>* decls) override { 1648 void VisitDeclarations(ZoneList<Declaration*>* decls) override {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1714 uint32_t index = builder_->AddFunction(); 1731 uint32_t index = builder_->AddFunction();
1715 IndexContainer* container = new (zone()) IndexContainer(); 1732 IndexContainer* container = new (zone()) IndexContainer();
1716 container->index = index; 1733 container->index = index;
1717 entry = functions_.LookupOrInsert(v, ComputePointerHash(v), 1734 entry = functions_.LookupOrInsert(v, ComputePointerHash(v),
1718 ZoneAllocationPolicy(zone())); 1735 ZoneAllocationPolicy(zone()));
1719 entry->value = container; 1736 entry->value = container;
1720 } 1737 }
1721 return (reinterpret_cast<IndexContainer*>(entry->value))->index; 1738 return (reinterpret_cast<IndexContainer*>(entry->value))->index;
1722 } 1739 }
1723 1740
1724 LocalType TypeOf(Expression* expr) { 1741 LocalType TypeOf(Expression* expr) { return TypeFrom(typer_->TypeOf(expr)); }
1725 DCHECK_EQ(bounds_->get(expr).lower, bounds_->get(expr).upper);
1726 return TypeFrom(bounds_->get(expr).lower);
1727 }
1728 1742
1729 LocalType TypeFrom(Type* type) { 1743 LocalType TypeFrom(AsmType* type) {
1730 if (type->Is(cache_.kAsmInt)) { 1744 if (type->IsA(AsmType::Intish())) {
1731 return kAstI32; 1745 return kAstI32;
1732 } else if (type->Is(cache_.kAsmFloat)) { 1746 }
1747
1748 if (type->IsA(AsmType::Floatish())) {
1733 return kAstF32; 1749 return kAstF32;
1734 } else if (type->Is(cache_.kAsmDouble)) { 1750 }
1751
1752 if (type->IsA(AsmType::DoubleQ())) {
1735 return kAstF64; 1753 return kAstF64;
1736 } else {
1737 return kAstStmt;
1738 } 1754 }
1755
1756 return kAstStmt;
1739 } 1757 }
1740 1758
1741 Zone* zone() { return zone_; } 1759 Zone* zone() { return zone_; }
1742 1760
1743 ZoneHashMap local_variables_; 1761 ZoneHashMap local_variables_;
1744 ZoneHashMap functions_; 1762 ZoneHashMap functions_;
1745 ZoneHashMap global_variables_; 1763 ZoneHashMap global_variables_;
1746 AsmScope scope_; 1764 AsmScope scope_;
1747 WasmModuleBuilder* builder_; 1765 WasmModuleBuilder* builder_;
1748 WasmFunctionBuilder* current_function_builder_; 1766 WasmFunctionBuilder* current_function_builder_;
1749 FunctionLiteral* literal_; 1767 FunctionLiteral* literal_;
1750 Isolate* isolate_; 1768 Isolate* isolate_;
1751 Zone* zone_; 1769 Zone* zone_;
1752 AsmTyper* typer_; 1770 AsmTyper* typer_;
1753 TypeCache const& cache_;
1754 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; 1771 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
1755 ZoneVector<ForeignVariable> foreign_variables_; 1772 ZoneVector<ForeignVariable> foreign_variables_;
1756 uint32_t init_function_index_; 1773 uint32_t init_function_index_;
1757 uint32_t foreign_init_function_index_; 1774 uint32_t foreign_init_function_index_;
1758 uint32_t next_table_index_; 1775 uint32_t next_table_index_;
1759 ZoneHashMap function_tables_; 1776 ZoneHashMap function_tables_;
1760 ImportedFunctionTable imported_function_table_; 1777 ImportedFunctionTable imported_function_table_;
1761 const AstTypeBounds* bounds_;
1762 1778
1763 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); 1779 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
1764 1780
1765 private: 1781 private:
1766 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); 1782 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl);
1767 }; 1783 };
1768 1784
1769 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, 1785 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone,
1770 FunctionLiteral* literal, AsmTyper* typer) 1786 FunctionLiteral* literal, AsmTyper* typer)
1771 : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {} 1787 : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {}
1772 1788
1773 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so 1789 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so
1774 // that zone in constructor may be thrown away once wasm module is written. 1790 // that zone in constructor may be thrown away once wasm module is written.
1775 ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) { 1791 ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) {
1776 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_); 1792 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_);
1777 impl.Build(); 1793 impl.Build();
1778 *foreign_args = impl.GetForeignArgs(); 1794 *foreign_args = impl.GetForeignArgs();
1779 ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_); 1795 ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_);
1780 impl.builder_->WriteTo(*buffer); 1796 impl.builder_->WriteTo(*buffer);
1781 return buffer; 1797 return buffer;
1782 } 1798 }
1783 } // namespace wasm 1799 } // namespace wasm
1784 } // namespace internal 1800 } // namespace internal
1785 } // namespace v8 1801 } // namespace v8
OLDNEW
« no previous file with comments | « src/asmjs/asm-wasm-builder.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698