Index: src/wasm/asm-wasm-builder.cc |
diff --git a/src/wasm/asm-wasm-builder.cc b/src/wasm/asm-wasm-builder.cc |
index 00f459316f6a4d69581f1ca6039ccb9b3222b386..ccb272176eff0008f4c3e09bd2411a2921f5a7f7 100644 |
--- a/src/wasm/asm-wasm-builder.cc |
+++ b/src/wasm/asm-wasm-builder.cc |
@@ -28,7 +28,7 @@ namespace wasm { |
class AsmWasmBuilderImpl : public AstVisitor { |
public: |
AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, |
- Handle<Object> foreign) |
+ Handle<Object> foreign, AsmTyper* typer) |
: local_variables_(HashMap::PointersMatch, |
ZoneHashMap::kDefaultHashMapCapacity, |
ZoneAllocationPolicy(zone)), |
@@ -46,6 +46,7 @@ class AsmWasmBuilderImpl : public AstVisitor { |
isolate_(isolate), |
zone_(zone), |
foreign_(foreign), |
+ typer_(typer), |
cache_(TypeCache::Get()), |
breakable_blocks_(zone), |
block_size_(0), |
@@ -371,6 +372,67 @@ class AsmWasmBuilderImpl : public AstVisitor { |
RECURSE(Visit(expr->else_expression())); |
} |
+ bool VisitStdlibConstant(Variable* var) { |
+ AsmTyper::StandardMember standard_object = |
+ typer_->VariableAsStandardMember(var); |
+ switch (standard_object) { |
+ case AsmTyper::kInfinity: { |
+ double infinity = std::numeric_limits<double>::infinity(); |
+ byte code[] = {WASM_F64(infinity)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ case AsmTyper::kNaN: { |
+ double nan = std::numeric_limits<double>::signaling_NaN(); |
+ byte code[] = {WASM_F64(nan)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ case AsmTyper::kMathE: { |
+ byte code[] = {WASM_F64(M_E)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ case AsmTyper::kMathLN10: { |
+ byte code[] = {WASM_F64(M_LN10)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ case AsmTyper::kMathLN2: { |
+ byte code[] = {WASM_F64(M_LN2)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ case AsmTyper::kMathLOG10E: { |
+ byte code[] = {WASM_F64(M_LOG10E)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ case AsmTyper::kMathLOG2E: { |
+ byte code[] = {WASM_F64(M_LOG2E)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ case AsmTyper::kMathPI: { |
+ byte code[] = {WASM_F64(M_PI)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ case AsmTyper::kMathSQRT1_2: { |
+ byte code[] = {WASM_F64(M_SQRT1_2)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ case AsmTyper::kMathSQRT2: { |
+ byte code[] = {WASM_F64(M_SQRT2)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ default: { break; } |
+ } |
+ return false; |
+ } |
+ |
void VisitVariableProxy(VariableProxy* expr) { |
if (in_function_) { |
Variable* var = expr->var(); |
@@ -382,6 +444,9 @@ class AsmWasmBuilderImpl : public AstVisitor { |
} |
is_set_op_ = false; |
} else { |
+ if (VisitStdlibConstant(var)) { |
+ return; |
aseemgarg
2016/02/17 19:44:06
get rid of the return and instead make the conditi
bradn
2016/02/19 07:16:52
But I'm returning because I don't actually want to
|
+ } |
if (var->IsContextSlot()) { |
current_function_builder_->Emit(kExprLoadGlobal); |
} else { |
@@ -589,19 +654,28 @@ class AsmWasmBuilderImpl : public AstVisitor { |
UnLoadInitFunction(); |
return; |
} |
+ Property* prop = expr->value()->AsProperty(); |
+ if (prop != nullptr) { |
+ if (TypeOf(expr->value()) != kAstStmt) { |
+ // Assume it's part of stdlib. |
+ return; |
+ } |
+ } |
// TODO(bradnelson): Get rid of this. |
if (TypeOf(expr->value()) == kAstStmt) { |
Property* prop = expr->value()->AsProperty(); |
if (prop != nullptr) { |
VariableProxy* vp = prop->obj()->AsVariableProxy(); |
- if (vp != nullptr && vp->var()->IsParameter() && |
- vp->var()->index() == 1) { |
- VariableProxy* target = expr->target()->AsVariableProxy(); |
- if (target->bounds().lower->Is(Type::Function())) { |
- const AstRawString* name = |
- prop->key()->AsLiteral()->AsRawPropertyName(); |
- imported_function_table_.AddImport( |
- target->var(), name->raw_data(), name->length()); |
+ if (vp != nullptr && vp->var()->IsParameter()) { |
aseemgarg
2016/02/17 19:44:06
what's the change here?
bradn
2016/02/19 07:16:52
Oops, dropped.
|
+ fprintf(stderr, "%d\n", vp->var()->index()); |
aseemgarg
2016/02/17 19:44:06
get rid of fprintf
bradn
2016/02/19 07:16:52
Done.
|
+ if (vp->var()->index() == 1) { |
+ VariableProxy* target = expr->target()->AsVariableProxy(); |
+ if (target->bounds().lower->Is(Type::Function())) { |
+ const AstRawString* name = |
+ prop->key()->AsLiteral()->AsRawPropertyName(); |
+ imported_function_table_.AddImport( |
+ target->var(), name->raw_data(), name->length()); |
+ } |
} |
} |
} |
@@ -765,11 +839,157 @@ class AsmWasmBuilderImpl : public AstVisitor { |
UNREACHABLE(); |
} |
+ bool VisitStdlibFunction(Call* call, VariableProxy* expr) { |
+ Variable* var = expr->var(); |
+ AsmTyper::StandardMember standard_object = |
+ typer_->VariableAsStandardMember(var); |
+ ZoneList<Expression*>* args = call->arguments(); |
+ LocalType call_type = TypeOf(call); |
+ switch (standard_object) { |
+ case AsmTyper::kNone: { |
+ return false; |
+ } |
+ case AsmTyper::kMathAcos: { |
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement as external. |
+ } |
+ case AsmTyper::kMathAsin: { |
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement as external. |
+ } |
+ case AsmTyper::kMathAtan: { |
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement as external. |
+ } |
+ case AsmTyper::kMathCos: { |
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement as external. |
+ } |
+ case AsmTyper::kMathSin: { |
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement as external. |
+ } |
+ case AsmTyper::kMathTan: { |
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement as external. |
+ } |
+ case AsmTyper::kMathExp: { |
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement as external. |
+ } |
+ case AsmTyper::kMathLog: { |
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement as external. |
+ } |
+ case AsmTyper::kMathCeil: { |
+ if (call_type == kAstF32) { |
+ current_function_builder_->Emit(kExprF32Ceil); |
+ } else if (call_type == kAstF64) { |
+ current_function_builder_->Emit(kExprF64Ceil); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ break; |
+ } |
+ case AsmTyper::kMathFloor: { |
+ if (call_type == kAstF32) { |
+ current_function_builder_->Emit(kExprF32Floor); |
+ } else if (call_type == kAstF64) { |
+ current_function_builder_->Emit(kExprF64Floor); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ break; |
+ } |
+ case AsmTyper::kMathSqrt: { |
+ if (call_type == kAstF32) { |
+ current_function_builder_->Emit(kExprF32Sqrt); |
+ } else if (call_type == kAstF64) { |
+ current_function_builder_->Emit(kExprF64Sqrt); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ break; |
+ } |
+ case AsmTyper::kMathAbs: { |
+ // TODO(bradnelson): Handle signed. |
+ if (call_type == kAstF32) { |
+ current_function_builder_->Emit(kExprF32Abs); |
+ } else if (call_type == kAstF64) { |
+ current_function_builder_->Emit(kExprF64Abs); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ break; |
+ } |
+ case AsmTyper::kMathMin: { |
+ // TODO(bradnelson): Handle signed. |
+ if (call_type == kAstF32) { |
+ current_function_builder_->Emit(kExprF32Min); |
titzer
2016/02/17 09:49:33
Can you double check that the JS min/max correspon
bradn
2016/02/19 07:16:53
Yes there is a difference around NaNs
I intend to
|
+ } else if (call_type == kAstF64) { |
+ current_function_builder_->Emit(kExprF64Min); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ break; |
+ } |
+ case AsmTyper::kMathMax: { |
+ // TODO(bradnelson): Handle signed. |
+ if (call_type == kAstF32) { |
+ current_function_builder_->Emit(kExprF32Max); |
+ } else if (call_type == kAstF64) { |
+ current_function_builder_->Emit(kExprF64Max); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ break; |
+ } |
+ case AsmTyper::kMathAtan2: { |
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement as external. |
+ } |
+ case AsmTyper::kMathPow: { |
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement as external. |
+ } |
+ case AsmTyper::kMathImul: { |
titzer
2016/02/17 09:49:33
Should be a simple kExprI32Mul.
bradn
2016/02/19 07:16:53
Done.
|
+ UNREACHABLE(); |
+ break; // TODO(bradnelson): Implement this inline. |
+ } |
+ case AsmTyper::kMathFround: { |
+ DCHECK(args->length() == 1); |
+ Literal* literal = args->at(0)->AsLiteral(); |
+ if (literal != NULL) { |
+ if (literal->raw_value()->IsNumber()) { |
+ float val = static_cast<float>(literal->raw_value()->AsNumber()); |
+ byte code[] = {WASM_F32(val)}; |
+ current_function_builder_->EmitCode(code, sizeof(code)); |
+ return true; |
+ } |
+ } |
+ break; |
+ } |
+ default: { break; } |
+ } |
+ // Visit arguments. |
+ for (int i = 0; i < args->length(); ++i) { |
+ Expression* arg = args->at(i); |
+ Visit(arg); |
+ } |
+ return true; |
+ } |
+ |
void VisitCall(Call* expr) { |
Call::CallType call_type = expr->GetCallType(isolate_); |
switch (call_type) { |
case Call::OTHER_CALL: { |
DCHECK(in_function_); |
+ VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
+ if (proxy != NULL) { |
+ if (VisitStdlibFunction(expr, proxy)) { |
+ return; |
+ } |
+ } |
uint16_t index; |
VariableProxy* vp = expr->expression()->AsVariableProxy(); |
if (vp != nullptr && |
@@ -1266,6 +1486,7 @@ class AsmWasmBuilderImpl : public AstVisitor { |
Isolate* isolate_; |
Zone* zone_; |
Handle<Object> foreign_; |
+ AsmTyper* typer_; |
TypeCache const& cache_; |
ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
int block_size_; |
@@ -1281,13 +1502,18 @@ class AsmWasmBuilderImpl : public AstVisitor { |
}; |
AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |
- FunctionLiteral* literal, Handle<Object> foreign) |
- : isolate_(isolate), zone_(zone), literal_(literal), foreign_(foreign) {} |
+ FunctionLiteral* literal, Handle<Object> foreign, |
+ AsmTyper* typer) |
+ : isolate_(isolate), |
+ zone_(zone), |
+ literal_(literal), |
+ foreign_(foreign), |
+ typer_(typer) {} |
// TODO(aseemgarg): probably should take zone (to write wasm to) as input so |
// that zone in constructor may be thrown away once wasm module is written. |
WasmModuleIndex* AsmWasmBuilder::Run() { |
- AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_); |
+ AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); |
impl.Compile(); |
WasmModuleWriter* writer = impl.builder_->Build(zone_); |
return writer->WriteTo(zone_); |