Commit 942ed114 authored by bradnelson's avatar bradnelson Committed by Commit bot

Properly handle unsigned literals, fix typing issue with unary +.

Properly convert unsigned literals.
Forbid using unary + on a kAsmInt.
Forbid multiplies other than * 1.0 as being equivalent to unary +.

BUG= https://bugs.chromium.org/p/v8/issues/detail?id=4203
TEST=test-asm-validator,asm-wasm
R=titzer@chromium.org,aseemgarg@chromium.org
LOG=N

Review URL: https://codereview.chromium.org/1832603002

Cr-Commit-Position: refs/heads/master@{#35046}
parent 3e0b6daf
......@@ -1281,12 +1281,27 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
return;
}
} else if (expr->op() == Token::MUL && expr->right()->IsLiteral() &&
right_type->Is(cache_.kAsmDouble)) {
right_type->Is(cache_.kAsmDouble) &&
expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) {
// For unary +, expressed as x * 1.0
if (expr->left()->IsCall() && expr->op() == Token::MUL &&
if (expr->left()->IsCall() &&
Type::Number()->Is(expr->left()->bounds().upper)) {
// Force the return types of foreign functions.
expr->left()->set_bounds(Bounds(cache_.kAsmDouble));
left_type = expr->left()->bounds().upper;
}
if (!(expr->left()->IsProperty() &&
Type::Number()->Is(expr->left()->bounds().upper))) {
if (!left_type->Is(cache_.kAsmSigned) &&
!left_type->Is(cache_.kAsmUnsigned) &&
!left_type->Is(cache_.kAsmFixnum) &&
!left_type->Is(cache_.kAsmFloatQ) &&
!left_type->Is(cache_.kAsmDoubleQ)) {
FAIL(
expr->left(),
"unary + only allowed on signed, unsigned, float?, or double?");
}
}
IntersectResult(expr, cache_.kAsmDouble);
return;
......
......@@ -461,33 +461,32 @@ class AsmWasmBuilderImpl : public AstVisitor {
}
void VisitLiteral(Literal* expr) {
if (in_function_) {
if (expr->raw_value()->IsNumber()) {
LocalType type = TypeOf(expr);
switch (type) {
case kAstI32: {
int val = static_cast<int>(expr->raw_value()->AsNumber());
// TODO(bradnelson): variable size
byte code[] = {WASM_I32V(val)};
current_function_builder_->EmitCode(code, sizeof(code));
break;
}
case kAstF32: {
float val = static_cast<float>(expr->raw_value()->AsNumber());
byte code[] = {WASM_F32(val)};
current_function_builder_->EmitCode(code, sizeof(code));
break;
}
case kAstF64: {
double val = static_cast<double>(expr->raw_value()->AsNumber());
byte code[] = {WASM_F64(val)};
current_function_builder_->EmitCode(code, sizeof(code));
break;
}
default:
UNREACHABLE();
}
Handle<Object> value = expr->value();
if (!in_function_ || !value->IsNumber()) {
return;
}
Type* type = expr->bounds().upper;
if (type->Is(cache_.kAsmSigned)) {
int32_t i;
if (!value->ToInt32(&i)) {
UNREACHABLE();
}
byte code[] = {WASM_I32V(i)};
current_function_builder_->EmitCode(code, sizeof(code));
} else if (type->Is(cache_.kAsmUnsigned) || type->Is(cache_.kAsmFixnum)) {
uint32_t u;
if (!value->ToUint32(&u)) {
UNREACHABLE();
}
int32_t i = static_cast<int32_t>(u);
byte code[] = {WASM_I32V(i)};
current_function_builder_->EmitCode(code, sizeof(code));
} else if (type->Is(cache_.kAsmDouble)) {
double val = expr->raw_value()->AsNumber();
byte code[] = {WASM_F64(val)};
current_function_builder_->EmitCode(code, sizeof(code));
} else {
UNREACHABLE();
}
}
......
......@@ -1985,6 +1985,20 @@ TEST(BadFunctionCallOutside) {
"asm: line 2: illegal variable reference in module body\n");
}
TEST(UnaryPlusOnIntForbidden) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1; return +x; }\n"
"function foo() { bar(); }",
"asm: line 1: "
"unary + only allowed on signed, unsigned, float?, or double?\n");
}
TEST(MultiplyNon1ConvertForbidden) {
CHECK_FUNC_ERROR(
"function bar() { var x = 0.0; return x * 2.0; }\n"
"function foo() { bar(); }",
"asm: line 1: invalid type annotation on binary op\n");
}
TEST(NestedVariableAssignment) {
CHECK_FUNC_TYPES_BEGIN(
......
......@@ -508,7 +508,7 @@ function TestConvertF64FromInt() {
function caller() {
var a = 1;
if ((+(a + a)) > 1.5) {
if ((+((a + a)|0)) > 1.5) {
return 25;
}
return 0;
......@@ -526,7 +526,7 @@ function TestConvertF64FromUnsigned() {
function caller() {
var a = 0xffffffff;
if ((+(a>>>0)) > 0.0) {
if((+a) < 0.0) {
if((+(a|0)) < 0.0) {
return 26;
}
}
......@@ -1376,6 +1376,21 @@ assertWasm(1, TestXor);
})();
(function TestBadCastFromInt() {
function Module(stdlib, foreign, heap) {
"use asm";
function func() {
var a = 1;
return +a;
}
return {func: func};
}
assertThrows(function() {
Wasm.instantiateModuleFromAsm(Module.toString());
});
})();
(function TestAndNegative() {
function Module() {
"use asm";
......@@ -1457,3 +1472,30 @@ assertWasm(1, TestXor);
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(1321347704, wasm.main());
})();
(function TestUnsignedLiterals() {
function asmModule() {
"use asm";
function u0xffffffff() {
var f = 0xffffffff;
return +(f >>> 0);
}
function u0x80000000() {
var f = 0x80000000;
return +(f >>> 0);
}
function u0x87654321() {
var f = 0x87654321;
return +(f >>> 0);
}
return {
u0xffffffff: u0xffffffff,
u0x80000000: u0x80000000,
u0x87654321: u0x87654321,
};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(0xffffffff, wasm.u0xffffffff());
assertEquals(0x80000000, wasm.u0x80000000());
assertEquals(0x87654321, wasm.u0x87654321());
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment