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

Fixing asm typing issues.

Fixing handling of uint32 to be more correct (previously some uint32's
were being interpreted as int32).
Fixing enforcement type matching in comparisons (previously mismatched
expressions could be compared).

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

Cr-Commit-Position: refs/heads/master@{#31726}
parent 88b764d7
...@@ -794,6 +794,26 @@ void AsmTyper::VisitCountOperation(CountOperation* expr) { ...@@ -794,6 +794,26 @@ void AsmTyper::VisitCountOperation(CountOperation* expr) {
} }
void AsmTyper::VisitIntegerBinaryOperation(BinaryOperation* expr,
Type* expected_type,
Type* result_type) {
RECURSE(VisitWithExpectation(expr->left(), expected_type,
"left bit operand expected to be integer"));
int left_intish = intish_;
RECURSE(VisitWithExpectation(expr->right(), expected_type,
"right bit operand expected to be integer"));
int right_intish = intish_;
if (left_intish > kMaxUncombinedAdditiveSteps) {
FAIL(expr, "too many consecutive additive ops");
}
if (right_intish > kMaxUncombinedAdditiveSteps) {
FAIL(expr, "too many consecutive additive ops");
}
intish_ = 0;
IntersectResult(expr, result_type);
}
void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) { switch (expr->op()) {
case Token::COMMA: { case Token::COMMA: {
...@@ -807,34 +827,24 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -807,34 +827,24 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
case Token::OR: case Token::OR:
case Token::AND: case Token::AND:
FAIL(expr, "logical operator encountered"); FAIL(expr, "logical operator encountered");
case Token::BIT_OR: case Token::BIT_OR: {
case Token::BIT_AND:
case Token::BIT_XOR:
case Token::SHL:
case Token::SHR:
case Token::SAR: {
// 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);
return;
}
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 (encoding ~).
Type* expectation = VisitIntegerBinaryOperation(expr, Type::Number(), cache_.kInt32);
expr->op() == Token::BIT_OR return;
? Type::Any()
: expr->op() == Token::BIT_XOR ? Type::Number() : cache_.kInt32;
Type* result =
expr->op() == Token::SHR ? Type::Unsigned32() : cache_.kInt32;
RECURSE(VisitWithExpectation(expr->left(), expectation,
"left bit operand expected to be integer"));
int left_intish = intish_;
RECURSE(VisitWithExpectation(expr->right(), expectation,
"right bit operand expected to be integer"));
int right_intish = intish_;
if (left_intish > kMaxUncombinedAdditiveSteps) {
FAIL(expr, "too many consecutive additive ops");
} }
if (right_intish > kMaxUncombinedAdditiveSteps) { case Token::SHR: {
FAIL(expr, "too many consecutive additive ops"); VisitIntegerBinaryOperation(expr, Type::Number(), cache_.kUint32);
return;
} }
intish_ = 0; case Token::SHL:
IntersectResult(expr, result); case Token::SAR:
case Token::BIT_AND: {
VisitIntegerBinaryOperation(expr, cache_.kInt32, cache_.kInt32);
return; return;
} }
case Token::ADD: case Token::ADD:
...@@ -899,7 +909,8 @@ void AsmTyper::VisitCompareOperation(CompareOperation* expr) { ...@@ -899,7 +909,8 @@ void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
Type* right_type = computed_type_; Type* right_type = computed_type_;
Type* type = Type::Union(left_type, right_type, zone()); Type* type = Type::Union(left_type, right_type, zone());
expr->set_combined_type(type); expr->set_combined_type(type);
if (type->Is(Type::Integral32()) || type->Is(Type::UntaggedFloat64())) { if (type->Is(cache_.kInt32) || type->Is(cache_.kUint32) ||
type->Is(cache_.kFloat32) || type->Is(cache_.kFloat64)) {
IntersectResult(expr, cache_.kInt32); IntersectResult(expr, cache_.kInt32);
} else { } else {
FAIL(expr, "ill-typed comparison operation"); FAIL(expr, "ill-typed comparison operation");
......
...@@ -84,6 +84,9 @@ class AsmTyper : public AstVisitor { ...@@ -84,6 +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,
Type* result_type);
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
#define DECLARE_VISIT(type) virtual void Visit##type(type* node) override; #define DECLARE_VISIT(type) virtual void Visit##type(type* node) override;
......
...@@ -516,6 +516,41 @@ TEST(ReturnVoid) { ...@@ -516,6 +516,41 @@ TEST(ReturnVoid) {
} }
TEST(EmptyBody) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { }\n"
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE);
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
CHECK_EXPR(Call, Bounds(Type::Undefined())) {
CHECK_VAR(bar, FUNC_V_TYPE);
}
}
}
CHECK_FUNC_TYPES_END
}
TEST(DoesNothing) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1.0; }\n"
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
CHECK_EXPR(Assignment, Bounds(cache.kFloat64)) {
CHECK_VAR(x, Bounds(cache.kFloat64));
CHECK_EXPR(Literal, Bounds(cache.kFloat64));
}
}
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
CHECK_EXPR(Call, Bounds(Type::Undefined())) {
CHECK_VAR(bar, FUNC_V_TYPE);
}
}
}
CHECK_FUNC_TYPES_END
}
TEST(ReturnInt32Literal) { TEST(ReturnInt32Literal) {
CHECK_FUNC_TYPES_BEGIN( CHECK_FUNC_TYPES_BEGIN(
"function bar() { return 1; }\n" "function bar() { return 1; }\n"
...@@ -618,6 +653,92 @@ TEST(Addition2) { ...@@ -618,6 +653,92 @@ TEST(Addition2) {
} }
TEST(UnsignedCompare) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; var y = 1; return ((x>>>0) < (y>>>0))|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(Assignment, Bounds(cache.kInt32)) {
CHECK_VAR(y, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(CompareOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(BinaryOperation, Bounds(cache.kUint32)) {
CHECK_VAR(x, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(BinaryOperation, Bounds(cache.kUint32)) {
CHECK_VAR(y, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
}
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
}
CHECK_SKIP();
}
CHECK_FUNC_TYPES_END
}
TEST(UnsignedDivide) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; var y = 1; return ((x>>>0) / (y>>>0))|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(Assignment, Bounds(cache.kInt32)) {
CHECK_VAR(y, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
CHECK_EXPR(BinaryOperation, Bounds(Type::None(), Type::Any())) {
CHECK_EXPR(BinaryOperation, Bounds(cache.kUint32)) {
CHECK_VAR(x, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(BinaryOperation, Bounds(cache.kUint32)) {
CHECK_VAR(y, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
}
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
}
CHECK_SKIP();
}
CHECK_FUNC_TYPES_END
}
TEST(FroundFloat32) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; return fround(x); }\n"
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_F_TYPE) {
CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
CHECK_VAR(x, Bounds(cache.kInt32));
CHECK_EXPR(Literal, Bounds(cache.kInt32));
}
CHECK_EXPR(Call, Bounds(cache.kFloat32)) {
CHECK_VAR(fround, FUNC_N2F_TYPE);
CHECK_VAR(x, Bounds(cache.kInt32));
}
}
CHECK_SKIP();
}
CHECK_FUNC_TYPES_END
}
TEST(Addition4) { TEST(Addition4) {
CHECK_FUNC_TYPES_BEGIN( CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; var y = 2; return (x+y+x+y)|0; }\n" "function bar() { var x = 1; var y = 2; return (x+y+x+y)|0; }\n"
...@@ -667,6 +788,30 @@ TEST(Division4) { ...@@ -667,6 +788,30 @@ TEST(Division4) {
} }
TEST(CompareMismatchInt32Float64) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1; var y = 2.0; return (x < y)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: ill-typed comparison operation\n");
}
TEST(CompareMismatchInt32Uint32) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1; var y = 2; return (x < (y>>>0))|0; }\n"
"function foo() { bar(); }",
"asm: line 39: ill-typed comparison operation\n");
}
TEST(CompareMismatchInt32Float32) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1; var y = 2; return (x < fround(y))|0; }\n"
"function foo() { bar(); }",
"asm: line 39: ill-typed comparison operation\n");
}
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