Chromium Code Reviews| Index: src/wasm/asm-wasm-builder.cc |
| diff --git a/src/wasm/asm-wasm-builder.cc b/src/wasm/asm-wasm-builder.cc |
| index abb69d5678565b5ebe91efa18f98c1dc1365e672..4e7549327128f92591662bdd6dddd980528f4e59 100644 |
| --- a/src/wasm/asm-wasm-builder.cc |
| +++ b/src/wasm/asm-wasm-builder.cc |
| @@ -75,8 +75,88 @@ class AsmWasmBuilderImpl : public AstVisitor { |
| current_function_builder_ = nullptr; |
| } |
| + void AddStdlibImport(const char* name, int kind, int args) { |
| + uint16_t index = builder_->AddFunction(); |
| + std_function_index_[kind] = index; |
| + WasmFunctionBuilder* b = builder_->FunctionAt(index); |
| + b->External(1); |
| + b->SetName(reinterpret_cast<const unsigned char*>(name), |
| + static_cast<int>(strlen(name))); |
| + b->ReturnType(kAstF64); |
| + for (int i = 0; i < args; ++i) { |
| + b->AddParam(kAstF64); |
| + } |
| + } |
| + |
| + void InitializeStdlibFunctions() { |
| + for (int i = 0; i < AsmTyper::kStdlibMax; ++i) { |
| + std_function_index_[i] = -1; |
| + } |
| + } |
| + |
| + void AddStdlibFunction(int kind) { |
| + const char* name = nullptr; |
| + int args = 0; |
| + switch (kind) { |
| + case AsmTyper::kMathAcos: |
| + name = "_acos"; |
| + args = 1; |
| + break; |
| + case AsmTyper::kMathAsin: |
| + name = "_asin"; |
| + args = 1; |
| + break; |
| + case AsmTyper::kMathAtan: |
| + name = "_atan"; |
| + args = 1; |
| + break; |
| + case AsmTyper::kMathCos: |
| + name = "_cos"; |
| + args = 1; |
| + break; |
| + case AsmTyper::kMathSin: |
| + name = "_sin"; |
| + args = 1; |
| + break; |
| + case AsmTyper::kMathTan: |
| + name = "_tan"; |
| + args = 1; |
| + break; |
| + case AsmTyper::kMathExp: |
| + name = "_exp"; |
| + args = 1; |
| + break; |
| + case AsmTyper::kMathLog: |
| + name = "_log"; |
| + args = 1; |
| + break; |
| + case AsmTyper::kMathAtan2: |
| + name = "_atan2"; |
| + args = 2; |
| + break; |
| + case AsmTyper::kMathPow: |
| + name = "_pow"; |
| + args = 2; |
| + break; |
| + } |
| + DCHECK(name != nullptr); |
| + AddStdlibImport(name, kind, args); |
| + } |
| + |
| + void EmitStdlibCall(int kind) { |
| + if (std_function_index_[kind] < 0) { |
| + AddStdlibFunction(kind); |
| + } |
| + current_function_builder_->Emit(kExprCallFunction); |
| + std::vector<uint8_t> index_arr = |
| + UnsignedLEB128From(std_function_index_[kind]); |
| + current_function_builder_->EmitCode( |
| + &index_arr[0], static_cast<uint32_t>(index_arr.size())); |
| + } |
| + |
| void Compile() { |
| InitializeInitFunction(); |
| + InitializeStdlibFunctions(); |
| RECURSE(VisitFunctionLiteral(literal_)); |
| } |
| @@ -842,36 +922,36 @@ class AsmWasmBuilderImpl : public AstVisitor { |
| return false; |
| } |
| case AsmTyper::kMathAcos: { |
| - UNREACHABLE(); |
| - break; // TODO(bradnelson): Implement as external. |
| + EmitStdlibCall(AsmTyper::kMathAcos); |
| + break; |
| } |
| case AsmTyper::kMathAsin: { |
| - UNREACHABLE(); |
| - break; // TODO(bradnelson): Implement as external. |
| + EmitStdlibCall(AsmTyper::kMathAsin); |
| + break; |
| } |
| case AsmTyper::kMathAtan: { |
| - UNREACHABLE(); |
| - break; // TODO(bradnelson): Implement as external. |
| + EmitStdlibCall(AsmTyper::kMathAtan); |
| + break; |
| } |
| case AsmTyper::kMathCos: { |
| - UNREACHABLE(); |
| - break; // TODO(bradnelson): Implement as external. |
| + EmitStdlibCall(AsmTyper::kMathCos); |
| + break; |
| } |
| case AsmTyper::kMathSin: { |
| - UNREACHABLE(); |
| - break; // TODO(bradnelson): Implement as external. |
| + EmitStdlibCall(AsmTyper::kMathSin); |
| + break; |
| } |
| case AsmTyper::kMathTan: { |
| - UNREACHABLE(); |
| - break; // TODO(bradnelson): Implement as external. |
| + EmitStdlibCall(AsmTyper::kMathTan); |
| + break; |
| } |
| case AsmTyper::kMathExp: { |
| - UNREACHABLE(); |
| - break; // TODO(bradnelson): Implement as external. |
| + EmitStdlibCall(AsmTyper::kMathExp); |
| + break; |
| } |
| case AsmTyper::kMathLog: { |
| - UNREACHABLE(); |
| - break; // TODO(bradnelson): Implement as external. |
| + EmitStdlibCall(AsmTyper::kMathLog); |
| + break; |
| } |
| case AsmTyper::kMathCeil: { |
| if (call_type == kAstF32) { |
| @@ -904,8 +984,17 @@ class AsmWasmBuilderImpl : public AstVisitor { |
| break; |
| } |
| case AsmTyper::kMathAbs: { |
|
titzer
2016/02/24 17:54:11
We're going to need some more extensive tests for
bradn
2016/02/24 18:07:29
Yeah this one is goofy, Math.abs is supposed to ha
|
| - // TODO(bradnelson): Handle signed. |
| - if (call_type == kAstF32) { |
| + // TODO(bradnelson): Should this be cast to float? |
| + if (call_type == kAstI32) { |
| + current_function_builder_->Emit(kExprIfElse); |
| + current_function_builder_->Emit(kExprI32LtS); |
| + Visit(args->at(0)); |
| + byte code[] = {WASM_I32(0)}; |
|
titzer
2016/02/24 17:54:11
WASM_I8
bradn
2016/02/24 18:07:29
Done.
|
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + current_function_builder_->Emit(kExprI32Sub); |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + Visit(args->at(0)); |
| + } else if (call_type == kAstF32) { |
| current_function_builder_->Emit(kExprF32Abs); |
| } else if (call_type == kAstF64) { |
| current_function_builder_->Emit(kExprF64Abs); |
| @@ -915,9 +1004,13 @@ class AsmWasmBuilderImpl : public AstVisitor { |
| break; |
| } |
| case AsmTyper::kMathMin: { |
| - // TODO(bradnelson): Handle signed. |
| // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. |
| - if (call_type == kAstF32) { |
| + if (call_type == kAstI32) { |
| + current_function_builder_->Emit(kExprIfElse); |
|
bradn
2016/02/24 18:07:29
Min and max have the same -(1<<31) issue it seems
|
| + current_function_builder_->Emit(kExprI32LeS); |
| + Visit(args->at(0)); |
| + Visit(args->at(1)); |
| + } else if (call_type == kAstF32) { |
| current_function_builder_->Emit(kExprF32Min); |
| } else if (call_type == kAstF64) { |
| current_function_builder_->Emit(kExprF64Min); |
| @@ -927,9 +1020,13 @@ class AsmWasmBuilderImpl : public AstVisitor { |
| break; |
| } |
| case AsmTyper::kMathMax: { |
| - // TODO(bradnelson): Handle signed. |
| // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. |
| - if (call_type == kAstF32) { |
| + if (call_type == kAstI32) { |
| + current_function_builder_->Emit(kExprIfElse); |
| + current_function_builder_->Emit(kExprI32GtS); |
| + Visit(args->at(0)); |
| + Visit(args->at(1)); |
| + } else if (call_type == kAstF32) { |
| current_function_builder_->Emit(kExprF32Max); |
| } else if (call_type == kAstF64) { |
| current_function_builder_->Emit(kExprF64Max); |
| @@ -939,12 +1036,12 @@ class AsmWasmBuilderImpl : public AstVisitor { |
| break; |
| } |
| case AsmTyper::kMathAtan2: { |
| - UNREACHABLE(); |
| - break; // TODO(bradnelson): Implement as external. |
| + EmitStdlibCall(AsmTyper::kMathAtan2); |
| + break; |
| } |
| case AsmTyper::kMathPow: { |
| - UNREACHABLE(); |
| - break; // TODO(bradnelson): Implement as external. |
| + EmitStdlibCall(AsmTyper::kMathPow); |
| + break; |
| } |
| case AsmTyper::kMathImul: { |
| current_function_builder_->Emit(kExprI32Mul); |
| @@ -1487,6 +1584,7 @@ class AsmWasmBuilderImpl : public AstVisitor { |
| uint32_t next_table_index_; |
| ZoneHashMap function_tables_; |
| ImportedFunctionTable imported_function_table_; |
| + int std_function_index_[AsmTyper::kStdlibMax]; |
| DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |