| Index: src/typing-asm.cc
|
| diff --git a/src/typing-asm.cc b/src/typing-asm.cc
|
| index ca80249b5665f1672fa41438e4cf760766d85475..92f7c12e8b8e34e7f34d7cb569a5e0f5e87497ff 100644
|
| --- a/src/typing-asm.cc
|
| +++ b/src/typing-asm.cc
|
| @@ -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 {
|
|
|