Commit 2cb3b9ea authored by bradnelson's avatar bradnelson Committed by Commit bot

Increase strictness of asm type conversions.

Only cast to integer with xor (closer to the spec which allows only ~~).
Check type matching on the bitwise operations.
Prevent mixing of types with the arthimetic operations.

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/1405383007

Cr-Commit-Position: refs/heads/master@{#31764}
parent 04db5bfa
...@@ -47,6 +47,8 @@ class TypeCache final { ...@@ -47,6 +47,8 @@ class TypeCache final {
Type* const kInteger = CreateRange(-V8_INFINITY, V8_INFINITY); Type* const kInteger = CreateRange(-V8_INFINITY, V8_INFINITY);
Type* const kWeakint = Type::Union(kInteger, Type::MinusZeroOrNaN(), zone()); Type* const kWeakint = Type::Union(kInteger, Type::MinusZeroOrNaN(), zone());
Type* const kIntegral32 = Type::Union(kInt32, kUint32, zone());
// The FixedArray::length property always containts a smi in the range // The FixedArray::length property always containts a smi in the range
// [0, FixedArray::kMaxLength]. // [0, FixedArray::kMaxLength].
Type* const kFixedArrayLengthType = CreateNative( Type* const kFixedArrayLengthType = CreateNative(
......
...@@ -446,8 +446,9 @@ void AsmTyper::VisitConditional(Conditional* expr) { ...@@ -446,8 +446,9 @@ void AsmTyper::VisitConditional(Conditional* expr) {
expr->else_expression(), expected_type_, expr->else_expression(), expected_type_,
"conditional else branch type mismatch with enclosing expression")); "conditional else branch type mismatch with enclosing expression"));
Type* else_type = computed_type_; Type* else_type = computed_type_;
Type* type = Type::Intersect(then_type, else_type, zone()); Type* type = Type::Union(then_type, else_type, zone());
if (!(type->Is(cache_.kInt32) || type->Is(cache_.kFloat64))) { if (!(type->Is(cache_.kInt32) || type->Is(cache_.kUint32) ||
type->Is(cache_.kFloat32) || type->Is(cache_.kFloat64))) {
FAIL(expr, "ill-typed conditional"); FAIL(expr, "ill-typed conditional");
} }
IntersectResult(expr, type); IntersectResult(expr, type);
...@@ -794,15 +795,18 @@ void AsmTyper::VisitCountOperation(CountOperation* expr) { ...@@ -794,15 +795,18 @@ void AsmTyper::VisitCountOperation(CountOperation* expr) {
} }
void AsmTyper::VisitIntegerBinaryOperation(BinaryOperation* expr, void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
Type* expected_type, Type* left_expected,
Type* result_type) { Type* right_expected,
RECURSE(VisitWithExpectation(expr->left(), expected_type, Type* result_type, bool conversion) {
RECURSE(VisitWithExpectation(expr->left(), left_expected,
"left bit operand expected to be integer")); "left bit operand expected to be integer"));
int left_intish = intish_; int left_intish = intish_;
RECURSE(VisitWithExpectation(expr->right(), expected_type, Type* left_type = computed_type_;
RECURSE(VisitWithExpectation(expr->right(), right_expected,
"right bit operand expected to be integer")); "right bit operand expected to be integer"));
int right_intish = intish_; int right_intish = intish_;
Type* right_type = computed_type_;
if (left_intish > kMaxUncombinedAdditiveSteps) { if (left_intish > kMaxUncombinedAdditiveSteps) {
FAIL(expr, "too many consecutive additive ops"); FAIL(expr, "too many consecutive additive ops");
} }
...@@ -810,6 +814,11 @@ void AsmTyper::VisitIntegerBinaryOperation(BinaryOperation* expr, ...@@ -810,6 +814,11 @@ void AsmTyper::VisitIntegerBinaryOperation(BinaryOperation* expr,
FAIL(expr, "too many consecutive additive ops"); FAIL(expr, "too many consecutive additive ops");
} }
intish_ = 0; intish_ = 0;
if (!conversion) {
if (!left_type->Is(right_type) || !right_type->Is(left_type)) {
FAIL(expr, "ill typed bitwise operation");
}
}
IntersectResult(expr, result_type); IntersectResult(expr, result_type);
} }
...@@ -829,22 +838,26 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -829,22 +838,26 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
FAIL(expr, "logical operator encountered"); FAIL(expr, "logical operator encountered");
case Token::BIT_OR: { case Token::BIT_OR: {
// BIT_OR allows Any since it is used as a type coercion. // BIT_OR allows Any since it is used as a type coercion.
VisitIntegerBinaryOperation(expr, Type::Any(), cache_.kInt32); VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kIntegral32,
cache_.kInt32, true);
return; return;
} }
case Token::BIT_XOR: { case Token::BIT_XOR: {
// BIT_XOR allows Number since it is used as a type coercion (encoding ~). // BIT_XOR allows Number since it is used as a type coercion (via ~~).
VisitIntegerBinaryOperation(expr, Type::Number(), cache_.kInt32); VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kIntegral32,
cache_.kInt32, true);
return; return;
} }
case Token::SHR: { case Token::SHR: {
VisitIntegerBinaryOperation(expr, Type::Number(), cache_.kUint32); VisitIntegerBitwiseOperator(expr, cache_.kIntegral32, cache_.kIntegral32,
cache_.kUint32, false);
return; return;
} }
case Token::SHL: case Token::SHL:
case Token::SAR: case Token::SAR:
case Token::BIT_AND: { case Token::BIT_AND: {
VisitIntegerBinaryOperation(expr, cache_.kInt32, cache_.kInt32); VisitIntegerBitwiseOperator(expr, cache_.kIntegral32, cache_.kIntegral32,
cache_.kInt32, false);
return; return;
} }
case Token::ADD: case Token::ADD:
...@@ -863,7 +876,7 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -863,7 +876,7 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
Type* right_type = computed_type_; Type* right_type = computed_type_;
int right_intish = intish_; int right_intish = intish_;
Type* type = Type::Union(left_type, right_type, zone()); Type* type = Type::Union(left_type, right_type, zone());
if (type->Is(cache_.kInt32)) { if (type->Is(cache_.kInt32) || type->Is(cache_.kUint32)) {
if (expr->op() == Token::MUL) { if (expr->op() == Token::MUL) {
if (!expr->left()->IsLiteral() && !expr->right()->IsLiteral()) { if (!expr->left()->IsLiteral() && !expr->right()->IsLiteral()) {
FAIL(expr, "direct integer multiply forbidden"); FAIL(expr, "direct integer multiply forbidden");
...@@ -885,7 +898,16 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -885,7 +898,16 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
IntersectResult(expr, cache_.kInt32); IntersectResult(expr, cache_.kInt32);
return; return;
} }
} else if (type->Is(Type::Number())) { } else if (expr->op() == Token::MUL &&
left_type->Is(cache_.kIntegral32) &&
right_type->Is(cache_.kFloat64)) {
// For unary +, expressed as x * 1.0
IntersectResult(expr, cache_.kFloat64);
return;
} else if (type->Is(cache_.kFloat32) && expr->op() != Token::MOD) {
IntersectResult(expr, cache_.kFloat32);
return;
} else if (type->Is(cache_.kFloat64)) {
IntersectResult(expr, cache_.kFloat64); IntersectResult(expr, cache_.kFloat64);
return; return;
} else { } else {
......
...@@ -84,8 +84,9 @@ class AsmTyper : public AstVisitor { ...@@ -84,8 +84,9 @@ class AsmTyper : public AstVisitor {
void VisitWithExpectation(Expression* expr, Type* expected_type, void VisitWithExpectation(Expression* expr, Type* expected_type,
const char* msg); const char* msg);
void VisitIntegerBinaryOperation(BinaryOperation* expr, Type* expected_type, void VisitIntegerBitwiseOperator(BinaryOperation* expr, Type* left_expected,
Type* result_type); Type* right_expected, Type* result_type,
bool conversion);
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
......
...@@ -719,6 +719,62 @@ TEST(UnsignedDivide) { ...@@ -719,6 +719,62 @@ TEST(UnsignedDivide) {
} }
TEST(UnsignedFromFloat64) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1.0; return (x>>>0)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: ill typed bitwise operation\n");
}
TEST(TypeMismatchAddInt32Float64) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1.0; var y = 0; return (x + y)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: ill-typed arithmetic operation\n");
}
TEST(TypeMismatchSubInt32Float64) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1.0; var y = 0; return (x - y)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: ill-typed arithmetic operation\n");
}
TEST(TypeMismatchDivInt32Float64) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1.0; var y = 0; return (x / y)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: ill-typed arithmetic operation\n");
}
TEST(TypeMismatchModInt32Float64) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1.0; var y = 0; return (x % y)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: ill-typed arithmetic operation\n");
}
TEST(ModFloat32) {
CHECK_FUNC_ERROR(
"function bar() { var x = fround(1.0); return (x % x)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: ill-typed arithmetic operation\n");
}
TEST(TernaryMismatchInt32Float64) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1; var y = 0.0; return (1 ? x : y)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: ill-typed conditional\n");
}
TEST(FroundFloat32) { TEST(FroundFloat32) {
CHECK_FUNC_TYPES_BEGIN( CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; return fround(x); }\n" "function bar() { var x = 1; return fround(x); }\n"
...@@ -812,6 +868,36 @@ TEST(CompareMismatchInt32Float32) { ...@@ -812,6 +868,36 @@ TEST(CompareMismatchInt32Float32) {
} }
TEST(Float64ToInt32) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; var y = 0.0; x = ~~y; }\n"
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
CHECK_VAR(x, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(Assignment, Bounds(cache.kFloat64)) {
CHECK_VAR(y, Bounds(cache.kFloat64));
CHECK_EXPR(Literal, Bounds(cache.kFloat64));
}
CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
CHECK_VAR(x, Bounds(cache.kInt32));
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_VAR(y, Bounds(cache.kFloat64));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
}
}
CHECK_SKIP();
}
CHECK_FUNC_TYPES_END
}
TEST(Load1) { TEST(Load1) {
CHECK_FUNC_TYPES_BEGIN( CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; var y = i8[x>>0]|0; }\n" "function bar() { var x = 1; var y = i8[x>>0]|0; }\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