Commit ab1165fb authored by bradnelson's avatar bradnelson Committed by Commit bot

Fix ~ operator in asm typer, add more operator tests.

The ~ operator is de-sugared into true^x, which was
being improperly handled.

Adding tests of most bitwise operators and several error cases.

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

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

Cr-Commit-Position: refs/heads/master@{#31951}
parent b237b8a7
......@@ -841,7 +841,7 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
}
case Token::OR:
case Token::AND:
FAIL(expr, "logical operator encountered");
FAIL(expr, "illegal logical operator");
case Token::BIT_OR: {
// BIT_OR allows Any since it is used as a type coercion.
VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kIntegral32,
......@@ -849,6 +849,19 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
return;
}
case Token::BIT_XOR: {
// Handle booleans specially to handle de-sugared !
Literal* left = expr->left()->AsLiteral();
if (left && left->value()->IsBoolean()) {
if (left->ToBooleanIsTrue()) {
left->set_bounds(Bounds(cache_.kSingletonOne));
RECURSE(VisitWithExpectation(expr->right(), cache_.kIntegral32,
"not operator expects an integer"));
IntersectResult(expr, cache_.kInt32);
return;
} else {
FAIL(left, "unexpected false");
}
}
// BIT_XOR allows Number since it is used as a type coercion (via ~~).
VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kIntegral32,
cache_.kInt32, true);
......@@ -934,6 +947,11 @@ void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
RECURSE(
VisitWithExpectation(expr->right(), Type::Number(),
"right comparison operand expected to be number"));
Token::Value op = expr->op();
if (op != Token::EQ && op != Token::NE && op != Token::LT &&
op != Token::LTE && op != Token::GT && op != Token::GTE) {
FAIL(expr, "illegal comparison operator");
}
Type* right_type = computed_type_;
Type* type = Type::Union(left_type, right_type, zone());
expr->set_combined_type(type);
......
......@@ -653,6 +653,154 @@ TEST(Addition2) {
}
#define TEST_COMPARE_OP(name, op) \
TEST(name) { \
CHECK_FUNC_TYPES_BEGIN("function bar() { return (0 " op \
" 0)|0; }\n" \
"function foo() { bar(); }") { \
CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { \
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) { \
CHECK_EXPR(CompareOperation, Bounds(cache.kInt32)) { \
CHECK_EXPR(Literal, Bounds(cache.kInt32)); \
CHECK_EXPR(Literal, Bounds(cache.kInt32)); \
} \
CHECK_EXPR(Literal, Bounds(cache.kInt32)); \
} \
} \
CHECK_SKIP(); \
} \
CHECK_FUNC_TYPES_END \
}
TEST_COMPARE_OP(EqOperator, "==")
TEST_COMPARE_OP(LtOperator, "<")
TEST_COMPARE_OP(LteOperator, "<=")
TEST_COMPARE_OP(GtOperator, ">")
TEST_COMPARE_OP(GteOperator, ">=")
TEST(NeqOperator) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { return (0 != 0)|0; }\n"
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(UnaryOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(CompareOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(Literal, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
}
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
}
CHECK_SKIP();
}
CHECK_FUNC_TYPES_END
}
TEST(NotOperator) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 0; return (!x)|0; }\n"
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
CHECK_VAR(x, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(UnaryOperation, Bounds(cache.kInt32)) {
CHECK_VAR(x, Bounds(cache.kInt32));
}
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
}
CHECK_SKIP();
}
CHECK_FUNC_TYPES_END
}
TEST(InvertOperator) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 0; return (~x)|0; }\n"
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
CHECK_VAR(x, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_VAR(x, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
}
CHECK_SKIP();
}
CHECK_FUNC_TYPES_END
}
TEST(InvertConversion) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 0.0; return (~~x)|0; }\n"
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
CHECK_EXPR(Assignment, Bounds(cache.kFloat64)) {
CHECK_VAR(x, Bounds(cache.kFloat64));
CHECK_EXPR(Literal, Bounds(cache.kFloat64));
}
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_VAR(x, Bounds(cache.kFloat64));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
}
CHECK_SKIP();
}
CHECK_FUNC_TYPES_END
}
#define TEST_INT_BIN_OP(name, op) \
TEST(name) { \
CHECK_FUNC_TYPES_BEGIN("function bar() { var x = 0; return (x " op \
" 123)|0; }\n" \
"function foo() { bar(); }") { \
CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { \
CHECK_EXPR(Assignment, Bounds(cache.kInt32)) { \
CHECK_VAR(x, Bounds(cache.kInt32)); \
CHECK_EXPR(Literal, Bounds(cache.kInt32)); \
} \
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) { \
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) { \
CHECK_VAR(x, Bounds(cache.kInt32)); \
CHECK_EXPR(Literal, Bounds(cache.kInt32)); \
} \
CHECK_EXPR(Literal, Bounds(cache.kInt32)); \
} \
} \
CHECK_SKIP(); \
} \
CHECK_FUNC_TYPES_END \
}
TEST_INT_BIN_OP(AndOperator, "&")
TEST_INT_BIN_OP(OrOperator, "|")
TEST_INT_BIN_OP(XorOperator, "^")
TEST(UnsignedCompare) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; var y = 1; return ((x>>>0) < (y>>>0))|0; }\n"
......@@ -1127,6 +1275,62 @@ TEST(UnboundVariable) {
}
TEST(EqStrict) {
CHECK_FUNC_ERROR(
"function bar() { return (0 === 0)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: illegal comparison operator\n");
}
TEST(NeStrict) {
CHECK_FUNC_ERROR(
"function bar() { return (0 !== 0)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: illegal comparison operator\n");
}
TEST(InstanceOf) {
CHECK_FUNC_ERROR(
"function bar() { return (0 instanceof 0)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: illegal comparison operator\n");
}
TEST(InOperator) {
CHECK_FUNC_ERROR(
"function bar() { return (0 in 0)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: illegal comparison operator\n");
}
TEST(LogicalAndOperator) {
CHECK_FUNC_ERROR(
"function bar() { return (0 && 0)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: illegal logical operator\n");
}
TEST(LogicalOrOperator) {
CHECK_FUNC_ERROR(
"function bar() { return (0 || 0)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: illegal logical operator\n");
}
TEST(BadLiteral) {
CHECK_FUNC_ERROR(
"function bar() { return true | 0; }\n"
"function foo() { bar(); }",
"asm: line 39: illegal literal\n");
}
TEST(ForeignFunction) {
CHECK_FUNC_TYPES_BEGIN(
"var baz = foreign.baz;\n"
......
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