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}
This commit is contained in:
bradnelson 2015-11-02 16:29:15 -08:00 committed by Commit bot
parent 88b764d7f7
commit b0f7830bef
3 changed files with 186 additions and 27 deletions

View File

@ -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) {
switch (expr->op()) {
case Token::COMMA: {
@ -807,34 +827,24 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
case Token::OR:
case Token::AND:
FAIL(expr, "logical operator encountered");
case Token::BIT_OR:
case Token::BIT_AND:
case Token::BIT_XOR:
case Token::SHL:
case Token::SHR:
case Token::SAR: {
case Token::BIT_OR: {
// 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 ~).
Type* expectation =
expr->op() == Token::BIT_OR
? 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) {
FAIL(expr, "too many consecutive additive ops");
}
intish_ = 0;
IntersectResult(expr, result);
VisitIntegerBinaryOperation(expr, Type::Number(), cache_.kInt32);
return;
}
case Token::SHR: {
VisitIntegerBinaryOperation(expr, Type::Number(), cache_.kUint32);
return;
}
case Token::SHL:
case Token::SAR:
case Token::BIT_AND: {
VisitIntegerBinaryOperation(expr, cache_.kInt32, cache_.kInt32);
return;
}
case Token::ADD:
@ -899,7 +909,8 @@ void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
Type* right_type = computed_type_;
Type* type = Type::Union(left_type, right_type, zone());
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);
} else {
FAIL(expr, "ill-typed comparison operation");

View File

@ -84,6 +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);
Zone* zone() const { return zone_; }
#define DECLARE_VISIT(type) virtual void Visit##type(type* node) override;

View File

@ -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) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { return 1; }\n"
@ -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) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; var y = 2; return (x+y+x+y)|0; }\n"
@ -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) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = 1; var y = i8[x>>0]|0; }\n"