diff --git a/src/asmjs/asm-typer.cc b/src/asmjs/asm-typer.cc index 76cdf25456..eeac9e752b 100644 --- a/src/asmjs/asm-typer.cc +++ b/src/asmjs/asm-typer.cc @@ -1513,7 +1513,7 @@ AsmType* AsmTyper::ValidateCompareOperation(CompareOperation* cmp) { } namespace { -bool IsNegate(BinaryOperation* binop) { +bool IsInvert(BinaryOperation* binop) { if (binop->op() != Token::BIT_XOR) { return false; } @@ -1528,7 +1528,7 @@ bool IsNegate(BinaryOperation* binop) { } bool IsUnaryMinus(BinaryOperation* binop) { - // *VIOLATION* The parser replaces uses of +x with x*1.0. + // *VIOLATION* The parser replaces uses of -x with x*-1. if (binop->op() != Token::MUL) { return false; } @@ -1574,7 +1574,7 @@ AsmType* AsmTyper::ValidateBinaryOperation(BinaryOperation* expr) { } if (IsUnaryMinus(expr)) { - // *VIOLATION* the parser converts -x to x * -1.0. + // *VIOLATION* the parser converts -x to x * -1. AsmType* left_type; RECURSE(left_type = ValidateExpression(expr->left())); SetTypeOf(expr->right(), left_type); @@ -1599,11 +1599,11 @@ AsmType* AsmTyper::ValidateBinaryOperation(BinaryOperation* expr) { case Token::BIT_AND: return ValidateBitwiseANDExpression(expr); case Token::BIT_XOR: - if (IsNegate(expr)) { + if (IsInvert(expr)) { auto* left = expr->left(); auto* left_as_binop = left->AsBinaryOperation(); - if (left_as_binop != nullptr && IsNegate(left_as_binop)) { + if (left_as_binop != nullptr && IsInvert(left_as_binop)) { // This is the special ~~ operator. AsmType* left_type; RECURSE(left_type = ValidateExpression(left_as_binop->left())); diff --git a/src/asmjs/asm-wasm-builder.cc b/src/asmjs/asm-wasm-builder.cc index 301f7f45cf..213db14cf6 100644 --- a/src/asmjs/asm-wasm-builder.cc +++ b/src/asmjs/asm-wasm-builder.cc @@ -621,13 +621,31 @@ class AsmWasmBuilderImpl final : public AstVisitor { } else if (expr->raw_value()->IsFalse()) { byte code[] = {WASM_I32V(0)}; current_function_builder_->EmitCode(code, sizeof(code)); + } else if (expr->raw_value()->IsNumber()) { + // This can happen when -x becomes x * -1 (due to the parser). + int32_t i = 0; + if (!value->ToInt32(&i) || i != -1) { + UNREACHABLE(); + } + byte code[] = {WASM_I32V(i)}; + current_function_builder_->EmitCode(code, sizeof(code)); } else { UNREACHABLE(); } } else if (type->IsA(AsmType::Double())) { + // TODO(bradnelson): Pattern match the case where negation occurs and + // emit f64.neg instead. double val = expr->raw_value()->AsNumber(); byte code[] = {WASM_F64(val)}; current_function_builder_->EmitCode(code, sizeof(code)); + } else if (type->IsA(AsmType::Float())) { + // This can happen when -fround(x) becomes fround(x) * 1.0[float] + // (due to the parser). + // TODO(bradnelson): Pattern match this and emit f32.neg instead. + double val = expr->raw_value()->AsNumber(); + DCHECK_EQ(-1.0, val); + byte code[] = {WASM_F32(val)}; + current_function_builder_->EmitCode(code, sizeof(code)); } else { UNREACHABLE(); } diff --git a/test/mjsunit/wasm/asm-wasm-f32.js b/test/mjsunit/wasm/asm-wasm-f32.js index a5d5a6c2cc..66ef274796 100644 --- a/test/mjsunit/wasm/asm-wasm-f32.js +++ b/test/mjsunit/wasm/asm-wasm-f32.js @@ -159,6 +159,11 @@ function f32_gteq(a, b) { return 0; } +function f32_neg(a) { + a = fround(a); + return fround(-a); +} + var inputs = [ 0, 1, 2, 3, 4, @@ -211,6 +216,7 @@ var funcs = [ f32_lteq, f32_gt, f32_gteq, + f32_neg, ]; (function () { diff --git a/test/mjsunit/wasm/asm-wasm-f64.js b/test/mjsunit/wasm/asm-wasm-f64.js index 1fd51ff9d5..c7b439fede 100644 --- a/test/mjsunit/wasm/asm-wasm-f64.js +++ b/test/mjsunit/wasm/asm-wasm-f64.js @@ -205,21 +205,25 @@ function f64_tan(a) { return +Math_tan(+a); } -function f64_exp(a, b) { +function f64_exp(a) { a = +a; - b = +b; - return +Math_exp(+a, +b); + return +Math_exp(+a); } -function f64_log(a, b) { +function f64_log(a) { a = +a; - b = +b; - return +Math_log(+a, +b); + return +Math_log(+a); } -function f64_atan2(a) { +function f64_atan2(a, b) { a = +a; - return +Math_atan2(+a); + b = +b; + return +Math_atan2(+a, +b); +} + +function f64_neg(a) { + a = +a; + return +(-a); } @@ -272,17 +276,18 @@ var funcs = [ f64_floor, // TODO(bradnelson) f64_sqrt, f64_abs, + f64_neg, // TODO(bradnelson) f64_min is wrong for -0 // TODO(bradnelson) f64_max is wrong for -0 -// TODO(bradnelson) f64_acos, -// TODO(bradnelson) f64_asin, -// TODO(bradnelson) f64_atan, -// TODO(bradnelson) f64_cos, -// TODO(bradnelson) f64_sin, -// TODO(bradnelson) f64_tan, -// TODO(bradnelson) f64_exp, -// TODO(bradnelson) f64_log, -// TODO(bradnelson) f64_atan2, + f64_acos, + f64_asin, + f64_atan, + f64_cos, + f64_sin, + f64_tan, + f64_exp, + f64_log, + f64_atan2, ]; (function () { diff --git a/test/mjsunit/wasm/asm-wasm-i32.js b/test/mjsunit/wasm/asm-wasm-i32.js index 29f071c84c..9d8b14afec 100644 --- a/test/mjsunit/wasm/asm-wasm-i32.js +++ b/test/mjsunit/wasm/asm-wasm-i32.js @@ -180,6 +180,16 @@ function i32_abs(a) { return Math_abs(a | 0) | 0; } +function i32_neg(a) { + a = a | 0; + return (-a) | 0; +} + +function i32_invert(a) { + a = a | 0; + return (~a) | 0; +} + var inputs = [ 0, 1, 2, 3, 4, 10, 20, 30, 31, 32, 33, 100, 2000, @@ -226,7 +236,9 @@ var funcs = [ i32_gteq, i32_min, i32_max, - i32_abs + i32_abs, + i32_neg, + i32_invert, ]; (function () { diff --git a/test/mjsunit/wasm/asm-wasm-u32.js b/test/mjsunit/wasm/asm-wasm-u32.js index 8276015214..0809bca6ab 100644 --- a/test/mjsunit/wasm/asm-wasm-u32.js +++ b/test/mjsunit/wasm/asm-wasm-u32.js @@ -157,6 +157,16 @@ function u32_gteq(a, b) { return 0; } +function u32_neg(a) { + a = a | 0; + return (-a) | 0; +} + +function u32_invert(a) { + a = a | 0; + return (~a) | 0; +} + var inputs = [ 0, 1, 2, 3, 4, @@ -202,6 +212,8 @@ var funcs = [ u32_lteq, u32_gt, u32_gteq, + u32_neg, + u32_invert, // TODO(titzer): u32_min // TODO(titzer): u32_max // TODO(titzer): u32_abs