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:
parent
88b764d7f7
commit
b0f7830bef
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user