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 {
Type* const kInteger = CreateRange(-V8_INFINITY, V8_INFINITY);
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
// [0, FixedArray::kMaxLength].
Type* const kFixedArrayLengthType = CreateNative(
......
......@@ -446,8 +446,9 @@ void AsmTyper::VisitConditional(Conditional* expr) {
expr->else_expression(), expected_type_,
"conditional else branch type mismatch with enclosing expression"));
Type* else_type = computed_type_;
Type* type = Type::Intersect(then_type, else_type, zone());
if (!(type->Is(cache_.kInt32) || type->Is(cache_.kFloat64))) {
Type* type = Type::Union(then_type, else_type, zone());
if (!(type->Is(cache_.kInt32) || type->Is(cache_.kUint32) ||
type->Is(cache_.kFloat32) || type->Is(cache_.kFloat64))) {
FAIL(expr, "ill-typed conditional");
}
IntersectResult(expr, type);
......@@ -794,15 +795,18 @@ void AsmTyper::VisitCountOperation(CountOperation* expr) {
}
void AsmTyper::VisitIntegerBinaryOperation(BinaryOperation* expr,
Type* expected_type,
Type* result_type) {
RECURSE(VisitWithExpectation(expr->left(), expected_type,
void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
Type* left_expected,
Type* right_expected,
Type* result_type, bool conversion) {
RECURSE(VisitWithExpectation(expr->left(), left_expected,
"left bit operand expected to be integer"));
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"));
int right_intish = intish_;
Type* right_type = computed_type_;
if (left_intish > kMaxUncombinedAdditiveSteps) {
FAIL(expr, "too many consecutive additive ops");
}
......@@ -810,6 +814,11 @@ void AsmTyper::VisitIntegerBinaryOperation(BinaryOperation* expr,
FAIL(expr, "too many consecutive additive ops");
}
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);
}
......@@ -829,22 +838,26 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
FAIL(expr, "logical operator encountered");
case Token::BIT_OR: {
// 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;
}
case Token::BIT_XOR: {
// BIT_XOR allows Number since it is used as a type coercion (encoding ~).
VisitIntegerBinaryOperation(expr, Type::Number(), cache_.kInt32);
// BIT_XOR allows Number since it is used as a type coercion (via ~~).
VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kIntegral32,
cache_.kInt32, true);
return;
}
case Token::SHR: {
VisitIntegerBinaryOperation(expr, Type::Number(), cache_.kUint32);
VisitIntegerBitwiseOperator(expr, cache_.kIntegral32, cache_.kIntegral32,
cache_.kUint32, false);
return;
}
case Token::SHL:
case Token::SAR:
case Token::BIT_AND: {
VisitIntegerBinaryOperation(expr, cache_.kInt32, cache_.kInt32);
VisitIntegerBitwiseOperator(expr, cache_.kIntegral32, cache_.kIntegral32,
cache_.kInt32, false);
return;
}
case Token::ADD:
......@@ -863,7 +876,7 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
Type* right_type = computed_type_;
int right_intish = intish_;
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->left()->IsLiteral() && !expr->right()->IsLiteral()) {
FAIL(expr, "direct integer multiply forbidden");
......@@ -885,7 +898,16 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
IntersectResult(expr, cache_.kInt32);
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);
return;
} else {
......
......@@ -84,8 +84,9 @@ class AsmTyper : public AstVisitor {
void VisitWithExpectation(Expression* expr, Type* expected_type,
const char* msg);
void VisitIntegerBinaryOperation(BinaryOperation* expr, Type* expected_type,
Type* result_type);
void VisitIntegerBitwiseOperator(BinaryOperation* expr, Type* left_expected,
Type* right_expected, Type* result_type,
bool conversion);
Zone* zone() const { return zone_; }
......
......@@ -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) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; return fround(x); }\n"
......@@ -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) {
CHECK_FUNC_TYPES_BEGIN(
"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