Index: src/typing-asm.cc |
diff --git a/src/typing-asm.cc b/src/typing-asm.cc |
index da752418a63ba63e53b3c9e781c86817be7d60f0..3ebae9408aa13f9ec600af69a06bd97508b014bf 100644 |
--- a/src/typing-asm.cc |
+++ b/src/typing-asm.cc |
@@ -41,6 +41,8 @@ AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, |
script_(script), |
root_(root), |
valid_(true), |
+ intish_(0), |
+ assigning_(false), |
stdlib_types_(zone), |
stdlib_heap_types_(zone), |
stdlib_math_types_(zone), |
@@ -155,7 +157,7 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
if (literal) { |
RECURSE(VisitLiteral(literal, true)); |
} else { |
- RECURSE(VisitExpressionAnnotation(stmt->expression(), true)); |
+ RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true)); |
} |
expected_type_ = old_expected; |
result_type = computed_type_; |
@@ -179,7 +181,7 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
Variable* var = proxy->var(); |
if (var->location() != VariableLocation::PARAMETER || var->index() != i) |
break; |
- RECURSE(VisitExpressionAnnotation(expr->value(), false)); |
+ RECURSE(VisitExpressionAnnotation(expr->value(), var, false)); |
SetType(var, computed_type_); |
type->InitParameter(i, computed_type_); |
good = true; |
@@ -190,10 +192,20 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
} |
-void AsmTyper::VisitExpressionAnnotation(Expression* expr, bool is_return) { |
+void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, |
+ bool is_return) { |
// Normal +x or x|0 annotations. |
BinaryOperation* bin = expr->AsBinaryOperation(); |
if (bin != NULL) { |
+ if (var != NULL) { |
+ VariableProxy* left = bin->left()->AsVariableProxy(); |
+ if (!left) { |
+ FAIL(expr, "variable name expected in type annotation"); |
+ } |
+ if (left->var() != var) { |
+ FAIL(left, "variable type annotation references other variable"); |
+ } |
+ } |
Literal* right = bin->right()->AsLiteral(); |
if (right != NULL) { |
switch (bin->op()) { |
@@ -497,6 +509,7 @@ void AsmTyper::VisitVariableProxy(VariableProxy* expr) { |
} |
SetType(var, type); |
intish_ = 0; |
+ assigning_ = false; |
IntersectResult(expr, type); |
} |
@@ -593,18 +606,14 @@ void AsmTyper::VisitAssignment(Assignment* expr) { |
Type* type = expected_type_; |
RECURSE(VisitWithExpectation( |
expr->value(), type, "assignment value expected to match surrounding")); |
+ Type* target_type = StorageType(computed_type_); |
if (intish_ != 0) { |
- FAIL(expr, "value still an intish"); |
- } |
- Type* target_type = computed_type_; |
- if (target_type->Is(cache_.kAsmInt)) { |
- target_type = cache_.kAsmInt; |
+ FAIL(expr, "intish or floatish assignment"); |
} |
+ assigning_ = true; |
titzer
2015/11/24 07:32:32
At first glance this follow a stack discipline, bu
bradn
2015/11/30 20:34:44
So it turns out the spec allows nested assignment,
|
RECURSE(VisitWithExpectation(expr->target(), target_type, |
"assignment target expected to match value")); |
- if (intish_ != 0) { |
- FAIL(expr, "value still an intish"); |
- } |
+ DCHECK(!assigning_); |
IntersectResult(expr, computed_type_); |
} |
@@ -658,6 +667,7 @@ void AsmTyper::VisitHeapAccess(Property* expr) { |
FAIL(right, "call mask must match function table"); |
} |
bin->set_bounds(Bounds(cache_.kAsmSigned)); |
+ IntersectResult(expr, type); |
} else { |
Literal* literal = expr->key()->AsLiteral(); |
if (literal) { |
@@ -683,8 +693,34 @@ void AsmTyper::VisitHeapAccess(Property* expr) { |
} |
bin->set_bounds(Bounds(cache_.kAsmSigned)); |
} |
+ Type* result_type; |
+ if (type->Is(cache_.kAsmIntArrayElement)) { |
+ result_type = cache_.kAsmIntQ; |
+ intish_ = kMaxUncombinedAdditiveSteps; |
+ } else if (type->Is(cache_.kAsmFloat)) { |
+ if (assigning_) { |
+ result_type = cache_.kAsmFloatDoubleQ; |
+ } else { |
+ result_type = cache_.kAsmFloatQ; |
+ } |
+ intish_ = 0; |
+ } else if (type->Is(cache_.kAsmDouble)) { |
+ if (assigning_) { |
+ result_type = cache_.kAsmFloatDoubleQ; |
+ if (intish_ != 0) { |
+ FAIL(expr, "Assignment of floatish to Float64Array"); |
+ } |
+ } else { |
+ result_type = cache_.kAsmDoubleQ; |
+ } |
+ intish_ = 0; |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ IntersectResult(expr, expected_type_); |
+ IntersectResult(expr, result_type); |
+ assigning_ = false; |
} |
- IntersectResult(expr, type); |
} |
@@ -780,6 +816,7 @@ void AsmTyper::VisitCall(Call* expr) { |
arg, fun_type->Parameter(i), |
"call argument expected to match callee parameter")); |
} |
+ intish_ = 0; |
IntersectResult(expr, fun_type->Result()); |
} else if (computed_type_->Is(Type::Any())) { |
// For foreign calls. |
@@ -789,6 +826,7 @@ void AsmTyper::VisitCall(Call* expr) { |
RECURSE(VisitWithExpectation(arg, Type::Any(), |
"foreign call argument expected to be any")); |
} |
+ intish_ = kMaxUncombinedAdditiveSteps; |
IntersectResult(expr, Type::Number()); |
} else { |
FAIL(expr, "invalid callee"); |
@@ -994,13 +1032,17 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
IntersectResult(expr, cache_.kAsmInt); |
return; |
} |
- } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmInt) && |
+ } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && |
right_type->Is(cache_.kAsmDouble)) { |
// For unary +, expressed as x * 1.0 |
IntersectResult(expr, cache_.kAsmDouble); |
return; |
} else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { |
+ if (left_intish != 0 || right_intish != 0) { |
+ FAIL(expr, "float operation before required fround"); |
+ } |
IntersectResult(expr, cache_.kAsmFloat); |
+ intish_ = 1; |
return; |
} else if (type->Is(cache_.kAsmDouble)) { |
IntersectResult(expr, cache_.kAsmDouble); |