Index: src/typing-asm.cc |
diff --git a/src/typing-asm.cc b/src/typing-asm.cc |
index 281491d638ad9696352e7632c8cdaa9d1bff922f..b47e88be7f2b498a24126de0257de912ae06127e 100644 |
--- a/src/typing-asm.cc |
+++ b/src/typing-asm.cc |
@@ -149,7 +149,15 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
if (body->length() > 0) { |
ReturnStatement* stmt = body->last()->AsReturnStatement(); |
if (stmt != NULL) { |
- RECURSE(VisitExpressionAnnotation(stmt->expression())); |
+ Literal* literal = stmt->expression()->AsLiteral(); |
+ Type* old_expected = expected_type_; |
+ expected_type_ = Type::Any(); |
+ if (literal) { |
+ RECURSE(VisitLiteral(literal, true)); |
+ } else { |
+ RECURSE(VisitExpressionAnnotation(stmt->expression(), true)); |
+ } |
+ expected_type_ = old_expected; |
result_type = computed_type_; |
} |
} |
@@ -171,7 +179,7 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
Variable* var = proxy->var(); |
if (var->location() != VariableLocation::PARAMETER || var->index() != i) |
break; |
- RECURSE(VisitExpressionAnnotation(expr->value())); |
+ RECURSE(VisitExpressionAnnotation(expr->value(), false)); |
SetType(var, computed_type_); |
type->InitParameter(i, computed_type_); |
good = true; |
@@ -182,24 +190,28 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
} |
-void AsmTyper::VisitExpressionAnnotation(Expression* expr) { |
+void AsmTyper::VisitExpressionAnnotation(Expression* expr, bool is_return) { |
// Normal +x or x|0 annotations. |
BinaryOperation* bin = expr->AsBinaryOperation(); |
if (bin != NULL) { |
Literal* right = bin->right()->AsLiteral(); |
if (right != NULL) { |
switch (bin->op()) { |
- case Token::MUL: // We encode +x as 1*x |
+ case Token::MUL: // We encode +x as x*1.0 |
if (right->raw_value()->ContainsDot() && |
right->raw_value()->AsNumber() == 1.0) { |
- SetResult(expr, cache_.kFloat64); |
+ SetResult(expr, cache_.kAsmDouble); |
return; |
} |
break; |
case Token::BIT_OR: |
if (!right->raw_value()->ContainsDot() && |
right->raw_value()->AsNumber() == 0.0) { |
- SetResult(expr, cache_.kInt32); |
+ if (is_return) { |
+ SetResult(expr, cache_.kAsmSigned); |
+ } else { |
+ SetResult(expr, cache_.kAsmInt); |
+ } |
return; |
} |
break; |
@@ -223,14 +235,14 @@ void AsmTyper::VisitExpressionAnnotation(Expression* expr) { |
call->expression(), Type::Any(zone()), |
"only fround allowed on expression annotations")); |
if (!computed_type_->Is( |
- Type::Function(cache_.kFloat32, Type::Number(zone()), zone()))) { |
+ Type::Function(cache_.kAsmFloat, Type::Number(zone()), zone()))) { |
FAIL(call->expression(), |
"only fround allowed on expression annotations"); |
} |
if (call->arguments()->length() != 1) { |
FAIL(call, "invalid argument count calling fround"); |
} |
- SetResult(expr, cache_.kFloat32); |
+ SetResult(expr, cache_.kAsmFloat); |
return; |
} |
} |
@@ -274,7 +286,7 @@ void AsmTyper::VisitIfStatement(IfStatement* stmt) { |
if (!in_function_) { |
FAIL(stmt, "if statement inside module body"); |
} |
- RECURSE(VisitWithExpectation(stmt->condition(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(stmt->condition(), cache_.kAsmSigned, |
"if condition expected to be integer")); |
RECURSE(Visit(stmt->then_statement())); |
RECURSE(Visit(stmt->else_statement())); |
@@ -300,6 +312,10 @@ void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) { |
if (!in_function_) { |
return; |
} |
+ // Returning literals handled in annotations. |
+ if (stmt->expression()->IsLiteral()) { |
+ return; |
+ } |
RECURSE( |
VisitWithExpectation(stmt->expression(), return_type_, |
"return expression expected to have return type")); |
@@ -315,15 +331,15 @@ void AsmTyper::VisitSwitchStatement(SwitchStatement* stmt) { |
if (!in_function_) { |
FAIL(stmt, "switch statement inside module body"); |
} |
- RECURSE(VisitWithExpectation(stmt->tag(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(stmt->tag(), cache_.kAsmSigned, |
"switch expression non-integer")); |
ZoneList<CaseClause*>* clauses = stmt->cases(); |
for (int i = 0; i < clauses->length(); ++i) { |
CaseClause* clause = clauses->at(i); |
if (clause->is_default()) continue; |
Expression* label = clause->label(); |
- RECURSE( |
- VisitWithExpectation(label, cache_.kInt32, "case label non-integer")); |
+ RECURSE(VisitWithExpectation(label, cache_.kAsmSigned, |
+ "case label non-integer")); |
if (!label->IsLiteral()) FAIL(label, "non-literal case label"); |
Handle<Object> value = label->AsLiteral()->value(); |
int32_t value32; |
@@ -343,7 +359,7 @@ void AsmTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { |
FAIL(stmt, "do statement inside module body"); |
} |
RECURSE(Visit(stmt->body())); |
- RECURSE(VisitWithExpectation(stmt->cond(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned, |
"do condition expected to be integer")); |
} |
@@ -352,7 +368,7 @@ void AsmTyper::VisitWhileStatement(WhileStatement* stmt) { |
if (!in_function_) { |
FAIL(stmt, "while statement inside module body"); |
} |
- RECURSE(VisitWithExpectation(stmt->cond(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned, |
"while condition expected to be integer")); |
RECURSE(Visit(stmt->body())); |
} |
@@ -366,7 +382,7 @@ void AsmTyper::VisitForStatement(ForStatement* stmt) { |
RECURSE(Visit(stmt->init())); |
} |
if (stmt->cond() != NULL) { |
- RECURSE(VisitWithExpectation(stmt->cond(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned, |
"for condition expected to be integer")); |
} |
if (stmt->next() != NULL) { |
@@ -436,22 +452,33 @@ void AsmTyper::VisitDoExpression(DoExpression* expr) { |
void AsmTyper::VisitConditional(Conditional* expr) { |
- RECURSE(VisitWithExpectation(expr->condition(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(expr->condition(), Type::Number(), |
"condition expected to be integer")); |
+ if (!computed_type_->Is(cache_.kAsmInt)) { |
+ FAIL(expr->condition(), "condition must be of type int"); |
+ } |
+ |
RECURSE(VisitWithExpectation( |
expr->then_expression(), expected_type_, |
"conditional then branch type mismatch with enclosing expression")); |
- Type* then_type = computed_type_; |
+ Type* then_type = StorageType(computed_type_); |
+ if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) { |
+ FAIL(expr->then_expression(), "invalid type in ? then expression"); |
+ } |
+ |
RECURSE(VisitWithExpectation( |
expr->else_expression(), expected_type_, |
"conditional else branch type mismatch with enclosing expression")); |
- Type* else_type = computed_type_; |
- 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"); |
+ Type* else_type = StorageType(computed_type_); |
+ if (intish_ != 0 || !else_type->Is(cache_.kAsmComparable)) { |
+ FAIL(expr->else_expression(), "invalid type in ? else expression"); |
} |
- IntersectResult(expr, type); |
+ |
+ if (!then_type->Is(else_type) || !else_type->Is(then_type)) { |
+ FAIL(expr, "then and else expressions in ? must have the same type"); |
+ } |
+ |
+ IntersectResult(expr, then_type); |
} |
@@ -461,8 +488,8 @@ void AsmTyper::VisitVariableProxy(VariableProxy* expr) { |
FAIL(expr, "unbound variable"); |
} |
Type* type = Type::Intersect(GetType(var), expected_type_, zone()); |
- if (type->Is(cache_.kInt32)) { |
- type = cache_.kInt32; |
+ if (type->Is(cache_.kAsmInt)) { |
+ type = cache_.kAsmInt; |
} |
SetType(var, type); |
intish_ = 0; |
@@ -470,22 +497,26 @@ void AsmTyper::VisitVariableProxy(VariableProxy* expr) { |
} |
-void AsmTyper::VisitLiteral(Literal* expr) { |
+void AsmTyper::VisitLiteral(Literal* expr, bool is_return) { |
intish_ = 0; |
Handle<Object> value = expr->value(); |
if (value->IsNumber()) { |
int32_t i; |
uint32_t u; |
if (expr->raw_value()->ContainsDot()) { |
- IntersectResult(expr, cache_.kFloat64); |
- } else if (value->ToUint32(&u)) { |
- IntersectResult(expr, cache_.kInt32); |
+ IntersectResult(expr, cache_.kAsmDouble); |
+ } else if (!is_return && value->ToUint32(&u)) { |
+ if (u <= 0x7fffffff) { |
+ IntersectResult(expr, cache_.kAsmFixnum); |
+ } else { |
+ IntersectResult(expr, cache_.kAsmUnsigned); |
+ } |
} else if (value->ToInt32(&i)) { |
- IntersectResult(expr, cache_.kInt32); |
+ IntersectResult(expr, cache_.kAsmSigned); |
} else { |
FAIL(expr, "illegal number"); |
} |
- } else if (value->IsString()) { |
+ } else if (!is_return && value->IsString()) { |
IntersectResult(expr, Type::String()); |
} else if (value->IsUndefined()) { |
IntersectResult(expr, Type::Undefined()); |
@@ -495,6 +526,9 @@ void AsmTyper::VisitLiteral(Literal* expr) { |
} |
+void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); } |
+ |
+ |
void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) { |
FAIL(expr, "regular expression encountered"); |
} |
@@ -558,7 +592,11 @@ void AsmTyper::VisitAssignment(Assignment* expr) { |
if (intish_ != 0) { |
FAIL(expr, "value still an intish"); |
} |
- RECURSE(VisitWithExpectation(expr->target(), computed_type_, |
+ Type* target_type = computed_type_; |
+ if (target_type->Is(cache_.kAsmInt)) { |
+ target_type = cache_.kAsmInt; |
+ } |
+ RECURSE(VisitWithExpectation(expr->target(), target_type, |
"assignment target expected to match value")); |
if (intish_ != 0) { |
FAIL(expr, "value still an intish"); |
@@ -578,16 +616,23 @@ void AsmTyper::VisitThrow(Throw* expr) { |
int AsmTyper::ElementShiftSize(Type* type) { |
- if (type->Is(cache_.kInt8) || type->Is(cache_.kUint8)) return 0; |
- if (type->Is(cache_.kInt16) || type->Is(cache_.kUint16)) return 1; |
- if (type->Is(cache_.kInt32) || type->Is(cache_.kUint32) || |
- type->Is(cache_.kFloat32)) |
- return 2; |
- if (type->Is(cache_.kFloat64)) return 3; |
+ if (type->Is(cache_.kAsmSize8)) return 0; |
+ if (type->Is(cache_.kAsmSize16)) return 1; |
+ if (type->Is(cache_.kAsmSize32)) return 2; |
+ if (type->Is(cache_.kAsmSize64)) return 3; |
return -1; |
} |
+Type* AsmTyper::StorageType(Type* type) { |
+ if (type->Is(cache_.kAsmInt)) { |
+ return cache_.kAsmInt; |
+ } else { |
+ return type; |
+ } |
+} |
+ |
+ |
void AsmTyper::VisitHeapAccess(Property* expr) { |
Type::ArrayType* array_type = computed_type_->AsArray(); |
size_t size = array_size_; |
@@ -597,42 +642,42 @@ void AsmTyper::VisitHeapAccess(Property* expr) { |
if (bin == NULL || bin->op() != Token::BIT_AND) { |
FAIL(expr->key(), "expected & in call"); |
} |
- RECURSE(VisitWithExpectation(bin->left(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, |
"array index expected to be integer")); |
Literal* right = bin->right()->AsLiteral(); |
if (right == NULL || right->raw_value()->ContainsDot()) { |
FAIL(right, "call mask must be integer"); |
} |
- RECURSE(VisitWithExpectation(bin->right(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, |
"call mask expected to be integer")); |
if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) { |
FAIL(right, "call mask must match function table"); |
} |
- bin->set_bounds(Bounds(cache_.kInt32)); |
+ bin->set_bounds(Bounds(cache_.kAsmSigned)); |
} else { |
Literal* literal = expr->key()->AsLiteral(); |
if (literal) { |
- RECURSE(VisitWithExpectation(literal, cache_.kInt32, |
+ RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned, |
"array index expected to be integer")); |
} else { |
BinaryOperation* bin = expr->key()->AsBinaryOperation(); |
if (bin == NULL || bin->op() != Token::SAR) { |
FAIL(expr->key(), "expected >> in heap access"); |
} |
- RECURSE(VisitWithExpectation(bin->left(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, |
"array index expected to be integer")); |
Literal* right = bin->right()->AsLiteral(); |
if (right == NULL || right->raw_value()->ContainsDot()) { |
FAIL(right, "heap access shift must be integer"); |
} |
- RECURSE(VisitWithExpectation(bin->right(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, |
"array shift expected to be integer")); |
int n = static_cast<int>(right->raw_value()->AsNumber()); |
int expected_shift = ElementShiftSize(type); |
if (expected_shift < 0 || n != expected_shift) { |
FAIL(right, "heap access shift must match element size"); |
} |
- bin->set_bounds(Bounds(cache_.kInt32)); |
+ bin->set_bounds(Bounds(cache_.kAsmSigned)); |
} |
} |
IntersectResult(expr, type); |
@@ -780,9 +825,9 @@ void AsmTyper::VisitCallRuntime(CallRuntime* expr) { |
void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { |
switch (expr->op()) { |
case Token::NOT: // Used to encode != and !== |
- RECURSE(VisitWithExpectation(expr->expression(), cache_.kInt32, |
+ RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, |
"operand expected to be integer")); |
- IntersectResult(expr, cache_.kInt32); |
+ IntersectResult(expr, cache_.kAsmSigned); |
return; |
case Token::DELETE: |
FAIL(expr, "delete operator encountered"); |
@@ -805,24 +850,40 @@ 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")); |
+ RECURSE(VisitWithExpectation(expr->left(), Type::Number(), |
+ "left bitwise operand expected to be a number")); |
int left_intish = intish_; |
Type* left_type = computed_type_; |
- RECURSE(VisitWithExpectation(expr->right(), right_expected, |
- "right bit operand expected to be integer")); |
+ if (!left_type->Is(left_expected)) { |
+ FAIL(expr->left(), "left bitwise operand expected to be an integer"); |
+ } |
+ if (left_intish > kMaxUncombinedAdditiveSteps) { |
+ FAIL(expr->left(), "too many consecutive additive ops"); |
+ } |
+ |
+ RECURSE( |
+ VisitWithExpectation(expr->right(), Type::Number(), |
+ "right bitwise operand expected to be a number")); |
int right_intish = intish_; |
Type* right_type = computed_type_; |
- if (left_intish > kMaxUncombinedAdditiveSteps) { |
- FAIL(expr, "too many consecutive additive ops"); |
+ if (!right_type->Is(right_expected)) { |
+ FAIL(expr->right(), "right bitwise operand expected to be an integer"); |
} |
if (right_intish > kMaxUncombinedAdditiveSteps) { |
- FAIL(expr, "too many consecutive additive ops"); |
+ FAIL(expr->right(), "too many consecutive additive ops"); |
} |
+ |
intish_ = 0; |
+ |
+ if (left_type->Is(cache_.kAsmFixnum) && right_type->Is(cache_.kAsmInt)) { |
+ left_type = right_type; |
+ } |
+ if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) { |
+ right_type = left_type; |
+ } |
if (!conversion) { |
if (!left_type->Is(right_type) || !right_type->Is(left_type)) { |
- FAIL(expr, "ill typed bitwise operation"); |
+ FAIL(expr, "ill-typed bitwise operation"); |
} |
} |
IntersectResult(expr, result_type); |
@@ -844,8 +905,8 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
FAIL(expr, "illegal logical operator"); |
case Token::BIT_OR: { |
// BIT_OR allows Any since it is used as a type coercion. |
- VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kIntegral32, |
- cache_.kInt32, true); |
+ VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt, |
+ cache_.kAsmSigned, true); |
return; |
} |
case Token::BIT_XOR: { |
@@ -854,29 +915,29 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
if (left && left->value()->IsBoolean()) { |
if (left->ToBooleanIsTrue()) { |
left->set_bounds(Bounds(cache_.kSingletonOne)); |
- RECURSE(VisitWithExpectation(expr->right(), cache_.kIntegral32, |
+ RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt, |
"not operator expects an integer")); |
- IntersectResult(expr, cache_.kInt32); |
+ IntersectResult(expr, cache_.kAsmSigned); |
return; |
} else { |
FAIL(left, "unexpected false"); |
} |
} |
// BIT_XOR allows Number since it is used as a type coercion (via ~~). |
- VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kIntegral32, |
- cache_.kInt32, true); |
+ VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kAsmInt, |
+ cache_.kAsmSigned, true); |
return; |
} |
case Token::SHR: { |
- VisitIntegerBitwiseOperator(expr, cache_.kIntegral32, cache_.kIntegral32, |
- cache_.kUint32, false); |
+ VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, |
+ cache_.kAsmUnsigned, false); |
return; |
} |
case Token::SHL: |
case Token::SAR: |
case Token::BIT_AND: { |
- VisitIntegerBitwiseOperator(expr, cache_.kIntegral32, cache_.kIntegral32, |
- cache_.kInt32, false); |
+ VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, |
+ cache_.kAsmSigned, false); |
return; |
} |
case Token::ADD: |
@@ -895,13 +956,25 @@ 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) || type->Is(cache_.kUint32)) { |
+ if (type->Is(cache_.kAsmInt)) { |
if (expr->op() == Token::MUL) { |
- if (!expr->left()->IsLiteral() && !expr->right()->IsLiteral()) { |
+ Literal* right = expr->right()->AsLiteral(); |
+ if (!right) { |
FAIL(expr, "direct integer multiply forbidden"); |
} |
- intish_ = 0; |
- IntersectResult(expr, cache_.kInt32); |
+ if (!right->value()->IsNumber()) { |
+ FAIL(expr, "multiply must be by an integer"); |
+ } |
+ int32_t i; |
+ if (!right->value()->ToInt32(&i)) { |
+ FAIL(expr, "multiply must be a signed integer"); |
+ } |
+ i = abs(i); |
+ if (i >= 1 << 20) { |
+ FAIL(expr, "multiply must be by value in -2^20 < n < 2^20"); |
+ } |
+ intish_ = i; |
+ IntersectResult(expr, cache_.kAsmInt); |
return; |
} else { |
intish_ = left_intish + right_intish + 1; |
@@ -914,20 +987,19 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
FAIL(expr, "too many consecutive multiplicative ops"); |
} |
} |
- IntersectResult(expr, cache_.kInt32); |
+ IntersectResult(expr, cache_.kAsmInt); |
return; |
} |
- } else if (expr->op() == Token::MUL && |
- left_type->Is(cache_.kIntegral32) && |
- right_type->Is(cache_.kFloat64)) { |
+ } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmInt) && |
+ right_type->Is(cache_.kAsmDouble)) { |
// For unary +, expressed as x * 1.0 |
- IntersectResult(expr, cache_.kFloat64); |
+ IntersectResult(expr, cache_.kAsmDouble); |
return; |
- } else if (type->Is(cache_.kFloat32) && expr->op() != Token::MOD) { |
- IntersectResult(expr, cache_.kFloat32); |
+ } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { |
+ IntersectResult(expr, cache_.kAsmFloat); |
return; |
- } else if (type->Is(cache_.kFloat64)) { |
- IntersectResult(expr, cache_.kFloat64); |
+ } else if (type->Is(cache_.kAsmDouble)) { |
+ IntersectResult(expr, cache_.kAsmDouble); |
return; |
} else { |
FAIL(expr, "ill-typed arithmetic operation"); |
@@ -940,27 +1012,33 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
void AsmTyper::VisitCompareOperation(CompareOperation* expr) { |
+ Token::Value op = expr->op(); |
+ if (op != Token::EQ && op != Token::NE && op != Token::LT && |
+ op != Token::LTE && op != Token::GT && op != Token::GTE) { |
+ FAIL(expr, "illegal comparison operator"); |
+ } |
+ |
RECURSE( |
VisitWithExpectation(expr->left(), Type::Number(), |
"left comparison operand expected to be number")); |
Type* left_type = computed_type_; |
+ if (!left_type->Is(cache_.kAsmComparable)) { |
+ FAIL(expr->left(), "bad type on left side of comparison"); |
+ } |
+ |
RECURSE( |
VisitWithExpectation(expr->right(), Type::Number(), |
"right comparison operand expected to be number")); |
- Token::Value op = expr->op(); |
- if (op != Token::EQ && op != Token::NE && op != Token::LT && |
- op != Token::LTE && op != Token::GT && op != Token::GTE) { |
- FAIL(expr, "illegal comparison operator"); |
- } |
Type* right_type = computed_type_; |
- Type* type = Type::Union(left_type, right_type, zone()); |
- expr->set_combined_type(type); |
- 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"); |
+ if (!right_type->Is(cache_.kAsmComparable)) { |
+ FAIL(expr->right(), "bad type on right side of comparison"); |
} |
+ |
+ if (!left_type->Is(right_type) && !right_type->Is(left_type)) { |
+ FAIL(expr, "left and right side of comparison must match"); |
+ } |
+ |
+ IntersectResult(expr, cache_.kAsmSigned); |
} |
@@ -1007,14 +1085,14 @@ void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { |
void AsmTyper::InitializeStdlib() { |
Type* number_type = Type::Number(zone()); |
- Type* double_type = cache_.kFloat64; |
+ Type* double_type = cache_.kAsmDouble; |
Type* double_fn1_type = Type::Function(double_type, double_type, zone()); |
Type* double_fn2_type = |
Type::Function(double_type, double_type, double_type, zone()); |
- Type* fround_type = Type::Function(cache_.kFloat32, number_type, zone()); |
+ Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone()); |
Type* imul_type = |
- Type::Function(cache_.kInt32, cache_.kInt32, cache_.kInt32, zone()); |
+ Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone()); |
// TODO(bradnelson): currently only approximating the proper intersection type |
// (which we cannot currently represent). |
Type* abs_type = Type::Function(number_type, number_type, zone()); |