OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/typing-asm.h" | 5 #include "src/typing-asm.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 if (use_asm == NULL) FAIL(fun, "missing \"use asm\""); | 82 if (use_asm == NULL) FAIL(fun, "missing \"use asm\""); |
83 Literal* use_asm_literal = use_asm->expression()->AsLiteral(); | 83 Literal* use_asm_literal = use_asm->expression()->AsLiteral(); |
84 if (use_asm_literal == NULL) FAIL(fun, "missing \"use asm\""); | 84 if (use_asm_literal == NULL) FAIL(fun, "missing \"use asm\""); |
85 if (!use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm")) | 85 if (!use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm")) |
86 FAIL(fun, "missing \"use asm\""); | 86 FAIL(fun, "missing \"use asm\""); |
87 | 87 |
88 // Module parameters. | 88 // Module parameters. |
89 for (int i = 0; i < scope->num_parameters(); ++i) { | 89 for (int i = 0; i < scope->num_parameters(); ++i) { |
90 Variable* param = scope->parameter(i); | 90 Variable* param = scope->parameter(i); |
91 DCHECK(GetType(param) == NULL); | 91 DCHECK(GetType(param) == NULL); |
92 SetType(param, Type::None(zone())); | 92 SetType(param, Type::None()); |
93 } | 93 } |
94 | 94 |
95 ZoneList<Declaration*>* decls = scope->declarations(); | 95 ZoneList<Declaration*>* decls = scope->declarations(); |
96 | 96 |
97 // Set all globals to type Any. | 97 // Set all globals to type Any. |
98 VariableDeclaration* decl = scope->function(); | 98 VariableDeclaration* decl = scope->function(); |
99 if (decl != NULL) SetType(decl->proxy()->var(), Type::None()); | 99 if (decl != NULL) SetType(decl->proxy()->var(), Type::None()); |
100 RECURSE(VisitDeclarations(scope->declarations())); | 100 RECURSE(VisitDeclarations(scope->declarations())); |
101 | 101 |
102 // Validate global variables. | 102 // Validate global variables. |
(...skipping 16 matching lines...) Expand all Loading... |
119 | 119 |
120 // Build function tables. | 120 // Build function tables. |
121 building_function_tables_ = true; | 121 building_function_tables_ = true; |
122 RECURSE(VisitStatements(fun->body())); | 122 RECURSE(VisitStatements(fun->body())); |
123 building_function_tables_ = false; | 123 building_function_tables_ = false; |
124 | 124 |
125 // Validate function bodies. | 125 // Validate function bodies. |
126 for (int i = 0; i < decls->length(); ++i) { | 126 for (int i = 0; i < decls->length(); ++i) { |
127 FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration(); | 127 FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration(); |
128 if (decl != NULL) { | 128 if (decl != NULL) { |
129 RECURSE( | 129 RECURSE(VisitWithExpectation(decl->fun(), Type::Any(), "UNREACHABLE")); |
130 VisitWithExpectation(decl->fun(), Type::Any(zone()), "UNREACHABLE")); | |
131 if (!computed_type_->IsFunction()) { | 130 if (!computed_type_->IsFunction()) { |
132 FAIL(decl->fun(), "function literal expected to be a function"); | 131 FAIL(decl->fun(), "function literal expected to be a function"); |
133 } | 132 } |
134 } | 133 } |
135 } | 134 } |
136 | 135 |
137 // Validate exports. | 136 // Validate exports. |
138 visiting_exports_ = true; | 137 visiting_exports_ = true; |
139 ReturnStatement* stmt = fun->body()->last()->AsReturnStatement(); | 138 ReturnStatement* stmt = fun->body()->last()->AsReturnStatement(); |
140 if (stmt == nullptr) { | 139 if (stmt == nullptr) { |
141 FAIL(fun->body()->last(), "last statement in module is not a return"); | 140 FAIL(fun->body()->last(), "last statement in module is not a return"); |
142 } | 141 } |
143 RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(), | 142 RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(), |
144 "expected object export")); | 143 "expected object export")); |
145 } | 144 } |
146 | 145 |
147 | 146 |
148 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) { | 147 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) { |
149 Variable* var = decl->proxy()->var(); | 148 Variable* var = decl->proxy()->var(); |
150 if (var->location() != VariableLocation::PARAMETER) { | 149 if (var->location() != VariableLocation::PARAMETER) { |
151 if (GetType(var) == NULL) { | 150 if (GetType(var) == NULL) { |
152 SetType(var, Type::Any(zone())); | 151 SetType(var, Type::Any()); |
153 } else { | 152 } else { |
154 DCHECK(!GetType(var)->IsFunction()); | 153 DCHECK(!GetType(var)->IsFunction()); |
155 } | 154 } |
156 } | 155 } |
157 DCHECK(GetType(var) != NULL); | 156 DCHECK(GetType(var) != NULL); |
158 intish_ = 0; | 157 intish_ = 0; |
159 } | 158 } |
160 | 159 |
161 | 160 |
162 void AsmTyper::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 161 void AsmTyper::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
163 if (in_function_) { | 162 if (in_function_) { |
164 FAIL(decl, "function declared inside another"); | 163 FAIL(decl, "function declared inside another"); |
165 } | 164 } |
166 // Set function type so global references to functions have some type | 165 // Set function type so global references to functions have some type |
167 // (so they can give a more useful error). | 166 // (so they can give a more useful error). |
168 Variable* var = decl->proxy()->var(); | 167 Variable* var = decl->proxy()->var(); |
169 SetType(var, Type::Function(zone())); | 168 SetType(var, Type::Function()); |
170 } | 169 } |
171 | 170 |
172 | 171 |
173 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { | 172 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
174 // Extract result type. | 173 // Extract result type. |
175 ZoneList<Statement*>* body = fun->body(); | 174 ZoneList<Statement*>* body = fun->body(); |
176 Type* result_type = Type::Undefined(zone()); | 175 Type* result_type = Type::Undefined(); |
177 if (body->length() > 0) { | 176 if (body->length() > 0) { |
178 ReturnStatement* stmt = body->last()->AsReturnStatement(); | 177 ReturnStatement* stmt = body->last()->AsReturnStatement(); |
179 if (stmt != NULL) { | 178 if (stmt != NULL) { |
180 Literal* literal = stmt->expression()->AsLiteral(); | 179 Literal* literal = stmt->expression()->AsLiteral(); |
181 Type* old_expected = expected_type_; | 180 Type* old_expected = expected_type_; |
182 expected_type_ = Type::Any(zone()); | 181 expected_type_ = Type::Any(); |
183 if (literal) { | 182 if (literal) { |
184 RECURSE(VisitLiteral(literal, true)); | 183 RECURSE(VisitLiteral(literal, true)); |
185 } else { | 184 } else { |
186 RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true)); | 185 RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true)); |
187 } | 186 } |
188 expected_type_ = old_expected; | 187 expected_type_ = old_expected; |
189 result_type = computed_type_; | 188 result_type = computed_type_; |
190 } | 189 } |
191 } | 190 } |
192 Type::FunctionType* type = Type::Function(result_type, Type::Any(zone()), | 191 Type* type = |
193 fun->parameter_count(), zone()) | 192 Type::Function(result_type, Type::Any(), fun->parameter_count(), zone()); |
194 ->AsFunction(); | |
195 | 193 |
196 // Extract parameter types. | 194 // Extract parameter types. |
197 bool good = true; | 195 bool good = true; |
198 for (int i = 0; i < fun->parameter_count(); ++i) { | 196 for (int i = 0; i < fun->parameter_count(); ++i) { |
199 good = false; | 197 good = false; |
200 if (i >= body->length()) break; | 198 if (i >= body->length()) break; |
201 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement(); | 199 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement(); |
202 if (stmt == NULL) break; | 200 if (stmt == NULL) break; |
203 Assignment* expr = stmt->expression()->AsAssignment(); | 201 Assignment* expr = stmt->expression()->AsAssignment(); |
204 if (expr == NULL || expr->is_compound()) break; | 202 if (expr == NULL || expr->is_compound()) break; |
205 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 203 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
206 if (proxy == NULL) break; | 204 if (proxy == NULL) break; |
207 Variable* var = proxy->var(); | 205 Variable* var = proxy->var(); |
208 if (var->location() != VariableLocation::PARAMETER || var->index() != i) | 206 if (var->location() != VariableLocation::PARAMETER || var->index() != i) |
209 break; | 207 break; |
210 RECURSE(VisitExpressionAnnotation(expr->value(), var, false)); | 208 RECURSE(VisitExpressionAnnotation(expr->value(), var, false)); |
211 if (property_info_ != NULL) { | 209 if (property_info_ != NULL) { |
212 SetVariableInfo(var, property_info_); | 210 SetVariableInfo(var, property_info_); |
213 property_info_ = NULL; | 211 property_info_ = NULL; |
214 } | 212 } |
215 SetType(var, computed_type_); | 213 SetType(var, computed_type_); |
216 type->InitParameter(i, computed_type_); | 214 type->AsFunction()->InitParameter(i, computed_type_); |
217 good = true; | 215 good = true; |
218 } | 216 } |
219 if (!good) FAIL(fun, "missing parameter type annotations"); | 217 if (!good) FAIL(fun, "missing parameter type annotations"); |
220 | 218 |
221 SetResult(fun, type); | 219 SetResult(fun, type); |
222 } | 220 } |
223 | 221 |
224 | 222 |
225 void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, | 223 void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, |
226 bool is_return) { | 224 bool is_return) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 break; | 257 break; |
260 default: | 258 default: |
261 break; | 259 break; |
262 } | 260 } |
263 } | 261 } |
264 FAIL(expr, "invalid type annotation on binary op"); | 262 FAIL(expr, "invalid type annotation on binary op"); |
265 } | 263 } |
266 | 264 |
267 // Numbers or the undefined literal (for empty returns). | 265 // Numbers or the undefined literal (for empty returns). |
268 if (expr->IsLiteral()) { | 266 if (expr->IsLiteral()) { |
269 RECURSE(VisitWithExpectation(expr, Type::Any(zone()), "invalid literal")); | 267 RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal")); |
270 return; | 268 return; |
271 } | 269 } |
272 | 270 |
273 Call* call = expr->AsCall(); | 271 Call* call = expr->AsCall(); |
274 if (call != NULL) { | 272 if (call != NULL) { |
275 VariableProxy* proxy = call->expression()->AsVariableProxy(); | 273 VariableProxy* proxy = call->expression()->AsVariableProxy(); |
276 if (proxy != NULL) { | 274 if (proxy != NULL) { |
277 VariableInfo* info = GetVariableInfo(proxy->var(), false); | 275 VariableInfo* info = GetVariableInfo(proxy->var(), false); |
278 if (!info || | 276 if (!info || |
279 (!info->is_check_function && !info->is_constructor_function)) { | 277 (!info->is_check_function && !info->is_constructor_function)) { |
(...skipping 29 matching lines...) Expand all Loading... |
309 } | 307 } |
310 } | 308 } |
311 | 309 |
312 | 310 |
313 void AsmTyper::VisitBlock(Block* stmt) { | 311 void AsmTyper::VisitBlock(Block* stmt) { |
314 RECURSE(VisitStatements(stmt->statements())); | 312 RECURSE(VisitStatements(stmt->statements())); |
315 } | 313 } |
316 | 314 |
317 | 315 |
318 void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) { | 316 void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) { |
319 RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(zone()), | 317 RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(), |
320 "expression statement expected to be any")); | 318 "expression statement expected to be any")); |
321 } | 319 } |
322 | 320 |
323 | 321 |
324 void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {} | 322 void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {} |
325 | 323 |
326 | 324 |
327 void AsmTyper::VisitSloppyBlockFunctionStatement( | 325 void AsmTyper::VisitSloppyBlockFunctionStatement( |
328 SloppyBlockFunctionStatement* stmt) { | 326 SloppyBlockFunctionStatement* stmt) { |
329 Visit(stmt->statement()); | 327 Visit(stmt->statement()); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) { | 359 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) { |
362 // Handle module return statement in VisitAsmModule. | 360 // Handle module return statement in VisitAsmModule. |
363 if (!in_function_) { | 361 if (!in_function_) { |
364 return; | 362 return; |
365 } | 363 } |
366 Literal* literal = stmt->expression()->AsLiteral(); | 364 Literal* literal = stmt->expression()->AsLiteral(); |
367 if (literal) { | 365 if (literal) { |
368 VisitLiteral(literal, true); | 366 VisitLiteral(literal, true); |
369 } else { | 367 } else { |
370 RECURSE( | 368 RECURSE( |
371 VisitWithExpectation(stmt->expression(), Type::Any(zone()), | 369 VisitWithExpectation(stmt->expression(), Type::Any(), |
372 "return expression expected to have return type")); | 370 "return expression expected to have return type")); |
373 } | 371 } |
374 if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) { | 372 if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) { |
375 FAIL(stmt->expression(), "return type does not match function signature"); | 373 FAIL(stmt->expression(), "return type does not match function signature"); |
376 } | 374 } |
377 } | 375 } |
378 | 376 |
379 | 377 |
380 void AsmTyper::VisitWithStatement(WithStatement* stmt) { | 378 void AsmTyper::VisitWithStatement(WithStatement* stmt) { |
381 FAIL(stmt, "bad with statement"); | 379 FAIL(stmt, "bad with statement"); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 if (in_function_) { | 491 if (in_function_) { |
494 FAIL(expr, "invalid nested function"); | 492 FAIL(expr, "invalid nested function"); |
495 } | 493 } |
496 Scope* scope = expr->scope(); | 494 Scope* scope = expr->scope(); |
497 DCHECK(scope->is_function_scope()); | 495 DCHECK(scope->is_function_scope()); |
498 | 496 |
499 if (!expr->bounds().upper->IsFunction()) { | 497 if (!expr->bounds().upper->IsFunction()) { |
500 FAIL(expr, "invalid function literal"); | 498 FAIL(expr, "invalid function literal"); |
501 } | 499 } |
502 | 500 |
503 Type::FunctionType* type = expr->bounds().upper->AsFunction(); | 501 Type* type = expr->bounds().upper; |
504 Type* save_return_type = return_type_; | 502 Type* save_return_type = return_type_; |
505 return_type_ = type->Result(); | 503 return_type_ = type->AsFunction()->Result(); |
506 in_function_ = true; | 504 in_function_ = true; |
507 local_variable_type_.Clear(); | 505 local_variable_type_.Clear(); |
508 RECURSE(VisitDeclarations(scope->declarations())); | 506 RECURSE(VisitDeclarations(scope->declarations())); |
509 RECURSE(VisitStatements(expr->body())); | 507 RECURSE(VisitStatements(expr->body())); |
510 in_function_ = false; | 508 in_function_ = false; |
511 return_type_ = save_return_type; | 509 return_type_ = save_return_type; |
512 IntersectResult(expr, type); | 510 IntersectResult(expr, type); |
513 } | 511 } |
514 | 512 |
515 | 513 |
516 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 514 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
517 FAIL(expr, "function info literal encountered"); | 515 FAIL(expr, "function info literal encountered"); |
518 } | 516 } |
519 | 517 |
520 | 518 |
521 void AsmTyper::VisitDoExpression(DoExpression* expr) { | 519 void AsmTyper::VisitDoExpression(DoExpression* expr) { |
522 FAIL(expr, "do-expression encountered"); | 520 FAIL(expr, "do-expression encountered"); |
523 } | 521 } |
524 | 522 |
525 | 523 |
526 void AsmTyper::VisitConditional(Conditional* expr) { | 524 void AsmTyper::VisitConditional(Conditional* expr) { |
527 if (!in_function_) { | 525 if (!in_function_) { |
528 FAIL(expr, "ternary operator inside module body"); | 526 FAIL(expr, "ternary operator inside module body"); |
529 } | 527 } |
530 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(zone()), | 528 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(), |
531 "condition expected to be integer")); | 529 "condition expected to be integer")); |
532 if (!computed_type_->Is(cache_.kAsmInt)) { | 530 if (!computed_type_->Is(cache_.kAsmInt)) { |
533 FAIL(expr->condition(), "condition must be of type int"); | 531 FAIL(expr->condition(), "condition must be of type int"); |
534 } | 532 } |
535 | 533 |
536 RECURSE(VisitWithExpectation( | 534 RECURSE(VisitWithExpectation( |
537 expr->then_expression(), expected_type_, | 535 expr->then_expression(), expected_type_, |
538 "conditional then branch type mismatch with enclosing expression")); | 536 "conditional then branch type mismatch with enclosing expression")); |
539 Type* then_type = StorageType(computed_type_); | 537 Type* then_type = StorageType(computed_type_); |
540 if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) { | 538 if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) { |
(...skipping 24 matching lines...) Expand all Loading... |
565 Variable* var = expr->var(); | 563 Variable* var = expr->var(); |
566 VariableInfo* info = GetVariableInfo(var, false); | 564 VariableInfo* info = GetVariableInfo(var, false); |
567 if (!assignment && !in_function_ && !building_function_tables_ && | 565 if (!assignment && !in_function_ && !building_function_tables_ && |
568 !visiting_exports_) { | 566 !visiting_exports_) { |
569 if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) { | 567 if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) { |
570 FAIL(expr, "illegal variable reference in module body"); | 568 FAIL(expr, "illegal variable reference in module body"); |
571 } | 569 } |
572 } | 570 } |
573 if (info == NULL || info->type == NULL) { | 571 if (info == NULL || info->type == NULL) { |
574 if (var->mode() == TEMPORARY) { | 572 if (var->mode() == TEMPORARY) { |
575 SetType(var, Type::Any(zone())); | 573 SetType(var, Type::Any()); |
576 info = GetVariableInfo(var, false); | 574 info = GetVariableInfo(var, false); |
577 } else { | 575 } else { |
578 FAIL(expr, "unbound variable"); | 576 FAIL(expr, "unbound variable"); |
579 } | 577 } |
580 } | 578 } |
581 if (property_info_ != NULL) { | 579 if (property_info_ != NULL) { |
582 SetVariableInfo(var, property_info_); | 580 SetVariableInfo(var, property_info_); |
583 property_info_ = NULL; | 581 property_info_ = NULL; |
584 } | 582 } |
585 Type* type = Type::Intersect(info->type, expected_type_, zone()); | 583 Type* type = Type::Intersect(info->type, expected_type_, zone()); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 | 628 |
631 | 629 |
632 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) { | 630 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) { |
633 if (in_function_) { | 631 if (in_function_) { |
634 FAIL(expr, "object literal in function"); | 632 FAIL(expr, "object literal in function"); |
635 } | 633 } |
636 // Allowed for asm module's export declaration. | 634 // Allowed for asm module's export declaration. |
637 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); | 635 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); |
638 for (int i = 0; i < props->length(); ++i) { | 636 for (int i = 0; i < props->length(); ++i) { |
639 ObjectLiteralProperty* prop = props->at(i); | 637 ObjectLiteralProperty* prop = props->at(i); |
640 RECURSE(VisitWithExpectation(prop->value(), Type::Any(zone()), | 638 RECURSE(VisitWithExpectation(prop->value(), Type::Any(), |
641 "object property expected to be a function")); | 639 "object property expected to be a function")); |
642 if (!computed_type_->IsFunction()) { | 640 if (!computed_type_->IsFunction()) { |
643 FAIL(prop->value(), "non-function in function table"); | 641 FAIL(prop->value(), "non-function in function table"); |
644 } | 642 } |
645 } | 643 } |
646 IntersectResult(expr, Type::Object(zone())); | 644 IntersectResult(expr, Type::Object()); |
647 } | 645 } |
648 | 646 |
649 | 647 |
650 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) { | 648 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) { |
651 if (in_function_) { | 649 if (in_function_) { |
652 FAIL(expr, "array literal inside a function"); | 650 FAIL(expr, "array literal inside a function"); |
653 } | 651 } |
654 // Allowed for function tables. | 652 // Allowed for function tables. |
655 ZoneList<Expression*>* values = expr->values(); | 653 ZoneList<Expression*>* values = expr->values(); |
656 Type* elem_type = Type::None(zone()); | 654 Type* elem_type = Type::None(); |
657 for (int i = 0; i < values->length(); ++i) { | 655 for (int i = 0; i < values->length(); ++i) { |
658 Expression* value = values->at(i); | 656 Expression* value = values->at(i); |
659 RECURSE(VisitWithExpectation(value, Type::Any(zone()), "UNREACHABLE")); | 657 RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE")); |
660 if (!computed_type_->IsFunction()) { | 658 if (!computed_type_->IsFunction()) { |
661 FAIL(value, "array component expected to be a function"); | 659 FAIL(value, "array component expected to be a function"); |
662 } | 660 } |
663 elem_type = Type::Union(elem_type, computed_type_, zone()); | 661 elem_type = Type::Union(elem_type, computed_type_, zone()); |
664 } | 662 } |
665 array_size_ = values->length(); | 663 array_size_ = values->length(); |
666 IntersectResult(expr, Type::Array(elem_type, zone())); | 664 IntersectResult(expr, Type::Array(elem_type, zone())); |
667 } | 665 } |
668 | 666 |
669 | 667 |
(...skipping 16 matching lines...) Expand all Loading... |
686 expr->value(), type, "assignment value expected to match surrounding")); | 684 expr->value(), type, "assignment value expected to match surrounding")); |
687 Type* target_type = StorageType(computed_type_); | 685 Type* target_type = StorageType(computed_type_); |
688 if (intish_ != 0) { | 686 if (intish_ != 0) { |
689 FAIL(expr, "intish or floatish assignment"); | 687 FAIL(expr, "intish or floatish assignment"); |
690 } | 688 } |
691 if (expr->target()->IsVariableProxy()) { | 689 if (expr->target()->IsVariableProxy()) { |
692 expected_type_ = target_type; | 690 expected_type_ = target_type; |
693 VisitVariableProxy(expr->target()->AsVariableProxy(), true); | 691 VisitVariableProxy(expr->target()->AsVariableProxy(), true); |
694 } else if (expr->target()->IsProperty()) { | 692 } else if (expr->target()->IsProperty()) { |
695 Property* property = expr->target()->AsProperty(); | 693 Property* property = expr->target()->AsProperty(); |
696 RECURSE(VisitWithExpectation(property->obj(), Type::Any(zone()), | 694 RECURSE(VisitWithExpectation(property->obj(), Type::Any(), |
697 "bad propety object")); | 695 "bad propety object")); |
698 if (!computed_type_->IsArray()) { | 696 if (!computed_type_->IsArray()) { |
699 FAIL(property->obj(), "array expected"); | 697 FAIL(property->obj(), "array expected"); |
700 } | 698 } |
701 VisitHeapAccess(property, true, target_type); | 699 VisitHeapAccess(property, true, target_type); |
702 } | 700 } |
703 IntersectResult(expr, target_type); | 701 IntersectResult(expr, target_type); |
704 } | 702 } |
705 | 703 |
706 | 704 |
(...skipping 20 matching lines...) Expand all Loading... |
727 if (type->Is(cache_.kAsmInt)) { | 725 if (type->Is(cache_.kAsmInt)) { |
728 return cache_.kAsmInt; | 726 return cache_.kAsmInt; |
729 } else { | 727 } else { |
730 return type; | 728 return type; |
731 } | 729 } |
732 } | 730 } |
733 | 731 |
734 | 732 |
735 void AsmTyper::VisitHeapAccess(Property* expr, bool assigning, | 733 void AsmTyper::VisitHeapAccess(Property* expr, bool assigning, |
736 Type* assignment_type) { | 734 Type* assignment_type) { |
737 Type::ArrayType* array_type = computed_type_->AsArray(); | 735 ArrayType* array_type = computed_type_->AsArray(); |
738 // size_t size = array_size_; | 736 // size_t size = array_size_; |
739 Type* type = array_type->AsArray()->Element(); | 737 Type* type = array_type->Element(); |
740 if (type->IsFunction()) { | 738 if (type->IsFunction()) { |
741 if (assigning) { | 739 if (assigning) { |
742 FAIL(expr, "assigning to function table is illegal"); | 740 FAIL(expr, "assigning to function table is illegal"); |
743 } | 741 } |
744 // TODO(bradnelson): Fix the parser and then un-comment this part | 742 // TODO(bradnelson): Fix the parser and then un-comment this part |
745 // BinaryOperation* bin = expr->key()->AsBinaryOperation(); | 743 // BinaryOperation* bin = expr->key()->AsBinaryOperation(); |
746 // if (bin == NULL || bin->op() != Token::BIT_AND) { | 744 // if (bin == NULL || bin->op() != Token::BIT_AND) { |
747 // FAIL(expr->key(), "expected & in call"); | 745 // FAIL(expr->key(), "expected & in call"); |
748 // } | 746 // } |
749 // RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, | 747 // RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 #undef V | 893 #undef V |
896 if (IsStdlibObject(expr->obj())) { | 894 if (IsStdlibObject(expr->obj())) { |
897 VisitLibraryAccess(&stdlib_types_, expr); | 895 VisitLibraryAccess(&stdlib_types_, expr); |
898 return; | 896 return; |
899 } | 897 } |
900 | 898 |
901 property_info_ = NULL; | 899 property_info_ = NULL; |
902 | 900 |
903 // Only recurse at this point so that we avoid needing | 901 // Only recurse at this point so that we avoid needing |
904 // stdlib.Math to have a real type. | 902 // stdlib.Math to have a real type. |
905 RECURSE(VisitWithExpectation(expr->obj(), Type::Any(zone()), | 903 RECURSE(VisitWithExpectation(expr->obj(), Type::Any(), "bad propety object")); |
906 "bad propety object")); | |
907 | 904 |
908 // For heap view or function table access. | 905 // For heap view or function table access. |
909 if (computed_type_->IsArray()) { | 906 if (computed_type_->IsArray()) { |
910 VisitHeapAccess(expr, false, NULL); | 907 VisitHeapAccess(expr, false, NULL); |
911 return; | 908 return; |
912 } | 909 } |
913 | 910 |
914 // stdlib.x or foreign.x | 911 // stdlib.x or foreign.x |
915 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 912 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
916 if (proxy != NULL) { | 913 if (proxy != NULL) { |
917 Variable* var = proxy->var(); | 914 Variable* var = proxy->var(); |
918 if (var->location() == VariableLocation::PARAMETER && var->index() == 1) { | 915 if (var->location() == VariableLocation::PARAMETER && var->index() == 1) { |
919 // foreign.x is ok. | 916 // foreign.x is ok. |
920 SetResult(expr, expected_type_); | 917 SetResult(expr, expected_type_); |
921 return; | 918 return; |
922 } | 919 } |
923 } | 920 } |
924 | 921 |
925 FAIL(expr, "invalid property access"); | 922 FAIL(expr, "invalid property access"); |
926 } | 923 } |
927 | 924 |
928 | 925 |
929 void AsmTyper::VisitCall(Call* expr) { | 926 void AsmTyper::VisitCall(Call* expr) { |
930 Type* expected_type = expected_type_; | 927 Type* expected_type = expected_type_; |
931 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(zone()), | 928 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), |
932 "callee expected to be any")); | 929 "callee expected to be any")); |
933 StandardMember standard_member = kNone; | 930 StandardMember standard_member = kNone; |
934 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 931 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
935 if (proxy) { | 932 if (proxy) { |
936 standard_member = VariableAsStandardMember(proxy->var()); | 933 standard_member = VariableAsStandardMember(proxy->var()); |
937 } | 934 } |
938 if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) { | 935 if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) { |
939 FAIL(expr, "calls forbidden outside function bodies"); | 936 FAIL(expr, "calls forbidden outside function bodies"); |
940 } | 937 } |
941 if (proxy == NULL && !expr->expression()->IsProperty()) { | 938 if (proxy == NULL && !expr->expression()->IsProperty()) { |
942 FAIL(expr, "calls must be to bound variables or function tables"); | 939 FAIL(expr, "calls must be to bound variables or function tables"); |
943 } | 940 } |
944 if (computed_type_->IsFunction()) { | 941 if (computed_type_->IsFunction()) { |
945 Type::FunctionType* fun_type = computed_type_->AsFunction(); | 942 FunctionType* fun_type = computed_type_->AsFunction(); |
946 Type* result_type = fun_type->Result(); | 943 Type* result_type = fun_type->Result(); |
947 ZoneList<Expression*>* args = expr->arguments(); | 944 ZoneList<Expression*>* args = expr->arguments(); |
948 if (fun_type->Arity() != args->length()) { | 945 if (fun_type->Arity() != args->length()) { |
949 FAIL(expr, "call with wrong arity"); | 946 FAIL(expr, "call with wrong arity"); |
950 } | 947 } |
951 for (int i = 0; i < args->length(); ++i) { | 948 for (int i = 0; i < args->length(); ++i) { |
952 Expression* arg = args->at(i); | 949 Expression* arg = args->at(i); |
953 RECURSE(VisitWithExpectation( | 950 RECURSE(VisitWithExpectation( |
954 arg, fun_type->Parameter(i), | 951 arg, fun_type->Parameter(i), |
955 "call argument expected to match callee parameter")); | 952 "call argument expected to match callee parameter")); |
(...skipping 20 matching lines...) Expand all Loading... |
976 Type* other = Type::Intersect(args->at(0)->bounds().upper, | 973 Type* other = Type::Intersect(args->at(0)->bounds().upper, |
977 args->at(1)->bounds().upper, zone()); | 974 args->at(1)->bounds().upper, zone()); |
978 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) && | 975 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) && |
979 !other->Is(cache_.kAsmSigned)) { | 976 !other->Is(cache_.kAsmSigned)) { |
980 FAIL(expr, "function arguments types don't match"); | 977 FAIL(expr, "function arguments types don't match"); |
981 } | 978 } |
982 } | 979 } |
983 } | 980 } |
984 intish_ = 0; | 981 intish_ = 0; |
985 IntersectResult(expr, result_type); | 982 IntersectResult(expr, result_type); |
986 } else if (computed_type_->Is(Type::Any(zone()))) { | 983 } else if (computed_type_->Is(Type::Any())) { |
987 // For foreign calls. | 984 // For foreign calls. |
988 ZoneList<Expression*>* args = expr->arguments(); | 985 ZoneList<Expression*>* args = expr->arguments(); |
989 for (int i = 0; i < args->length(); ++i) { | 986 for (int i = 0; i < args->length(); ++i) { |
990 Expression* arg = args->at(i); | 987 Expression* arg = args->at(i); |
991 RECURSE(VisitWithExpectation(arg, Type::Any(zone()), | 988 RECURSE(VisitWithExpectation(arg, Type::Any(), |
992 "foreign call argument expected to be any")); | 989 "foreign call argument expected to be any")); |
993 // Checking for asm extern types explicitly, as the type system | 990 // Checking for asm extern types explicitly, as the type system |
994 // doesn't correctly check their inheritance relationship. | 991 // doesn't correctly check their inheritance relationship. |
995 if (!computed_type_->Is(cache_.kAsmSigned) && | 992 if (!computed_type_->Is(cache_.kAsmSigned) && |
996 !computed_type_->Is(cache_.kAsmFixnum) && | 993 !computed_type_->Is(cache_.kAsmFixnum) && |
997 !computed_type_->Is(cache_.kAsmDouble)) { | 994 !computed_type_->Is(cache_.kAsmDouble)) { |
998 FAIL(arg, | 995 FAIL(arg, |
999 "foreign call argument expected to be int, double, or fixnum"); | 996 "foreign call argument expected to be int, double, or fixnum"); |
1000 } | 997 } |
1001 } | 998 } |
1002 intish_ = kMaxUncombinedAdditiveSteps; | 999 intish_ = kMaxUncombinedAdditiveSteps; |
1003 expr->expression()->set_bounds(Bounds(Type::Function(zone()))); | 1000 expr->expression()->set_bounds(Bounds(Type::Function())); |
1004 IntersectResult(expr, expected_type); | 1001 IntersectResult(expr, expected_type); |
1005 } else { | 1002 } else { |
1006 FAIL(expr, "invalid callee"); | 1003 FAIL(expr, "invalid callee"); |
1007 } | 1004 } |
1008 } | 1005 } |
1009 | 1006 |
1010 | 1007 |
1011 void AsmTyper::VisitCallNew(CallNew* expr) { | 1008 void AsmTyper::VisitCallNew(CallNew* expr) { |
1012 if (in_function_) { | 1009 if (in_function_) { |
1013 FAIL(expr, "new not allowed in module function"); | 1010 FAIL(expr, "new not allowed in module function"); |
1014 } | 1011 } |
1015 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(zone()), | 1012 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), |
1016 "expected stdlib function")); | 1013 "expected stdlib function")); |
1017 if (computed_type_->IsFunction()) { | 1014 if (computed_type_->IsFunction()) { |
1018 Type::FunctionType* fun_type = computed_type_->AsFunction(); | 1015 FunctionType* fun_type = computed_type_->AsFunction(); |
1019 ZoneList<Expression*>* args = expr->arguments(); | 1016 ZoneList<Expression*>* args = expr->arguments(); |
1020 if (fun_type->Arity() != args->length()) | 1017 if (fun_type->Arity() != args->length()) |
1021 FAIL(expr, "call with wrong arity"); | 1018 FAIL(expr, "call with wrong arity"); |
1022 for (int i = 0; i < args->length(); ++i) { | 1019 for (int i = 0; i < args->length(); ++i) { |
1023 Expression* arg = args->at(i); | 1020 Expression* arg = args->at(i); |
1024 RECURSE(VisitWithExpectation( | 1021 RECURSE(VisitWithExpectation( |
1025 arg, fun_type->Parameter(i), | 1022 arg, fun_type->Parameter(i), |
1026 "constructor argument expected to match callee parameter")); | 1023 "constructor argument expected to match callee parameter")); |
1027 } | 1024 } |
1028 IntersectResult(expr, fun_type->Result()); | 1025 IntersectResult(expr, fun_type->Result()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1062 | 1059 |
1063 void AsmTyper::VisitCountOperation(CountOperation* expr) { | 1060 void AsmTyper::VisitCountOperation(CountOperation* expr) { |
1064 FAIL(expr, "increment or decrement operator encountered"); | 1061 FAIL(expr, "increment or decrement operator encountered"); |
1065 } | 1062 } |
1066 | 1063 |
1067 | 1064 |
1068 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, | 1065 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, |
1069 Type* left_expected, | 1066 Type* left_expected, |
1070 Type* right_expected, | 1067 Type* right_expected, |
1071 Type* result_type, bool conversion) { | 1068 Type* result_type, bool conversion) { |
1072 RECURSE(VisitWithExpectation(expr->left(), Type::Number(zone()), | 1069 RECURSE(VisitWithExpectation(expr->left(), Type::Number(), |
1073 "left bitwise operand expected to be a number")); | 1070 "left bitwise operand expected to be a number")); |
1074 int left_intish = intish_; | 1071 int left_intish = intish_; |
1075 Type* left_type = computed_type_; | 1072 Type* left_type = computed_type_; |
1076 if (!left_type->Is(left_expected)) { | 1073 if (!left_type->Is(left_expected)) { |
1077 FAIL(expr->left(), "left bitwise operand expected to be an integer"); | 1074 FAIL(expr->left(), "left bitwise operand expected to be an integer"); |
1078 } | 1075 } |
1079 if (left_intish > kMaxUncombinedAdditiveSteps) { | 1076 if (left_intish > kMaxUncombinedAdditiveSteps) { |
1080 FAIL(expr->left(), "too many consecutive additive ops"); | 1077 FAIL(expr->left(), "too many consecutive additive ops"); |
1081 } | 1078 } |
1082 | 1079 |
1083 RECURSE( | 1080 RECURSE( |
1084 VisitWithExpectation(expr->right(), Type::Number(zone()), | 1081 VisitWithExpectation(expr->right(), Type::Number(), |
1085 "right bitwise operand expected to be a number")); | 1082 "right bitwise operand expected to be a number")); |
1086 int right_intish = intish_; | 1083 int right_intish = intish_; |
1087 Type* right_type = computed_type_; | 1084 Type* right_type = computed_type_; |
1088 if (!right_type->Is(right_expected)) { | 1085 if (!right_type->Is(right_expected)) { |
1089 FAIL(expr->right(), "right bitwise operand expected to be an integer"); | 1086 FAIL(expr->right(), "right bitwise operand expected to be an integer"); |
1090 } | 1087 } |
1091 if (right_intish > kMaxUncombinedAdditiveSteps) { | 1088 if (right_intish > kMaxUncombinedAdditiveSteps) { |
1092 FAIL(expr->right(), "too many consecutive additive ops"); | 1089 FAIL(expr->right(), "too many consecutive additive ops"); |
1093 } | 1090 } |
1094 | 1091 |
(...skipping 19 matching lines...) Expand all Loading... |
1114 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) { | 1111 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) { |
1115 FAIL(expr, "illegal binary operator inside module body"); | 1112 FAIL(expr, "illegal binary operator inside module body"); |
1116 } | 1113 } |
1117 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) || | 1114 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) || |
1118 !expr->right()->IsLiteral()) { | 1115 !expr->right()->IsLiteral()) { |
1119 FAIL(expr, "illegal computation inside module body"); | 1116 FAIL(expr, "illegal computation inside module body"); |
1120 } | 1117 } |
1121 } | 1118 } |
1122 switch (expr->op()) { | 1119 switch (expr->op()) { |
1123 case Token::COMMA: { | 1120 case Token::COMMA: { |
1124 RECURSE(VisitWithExpectation(expr->left(), Type::Any(zone()), | 1121 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), |
1125 "left comma operand expected to be any")); | 1122 "left comma operand expected to be any")); |
1126 RECURSE(VisitWithExpectation(expr->right(), Type::Any(zone()), | 1123 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), |
1127 "right comma operand expected to be any")); | 1124 "right comma operand expected to be any")); |
1128 IntersectResult(expr, computed_type_); | 1125 IntersectResult(expr, computed_type_); |
1129 return; | 1126 return; |
1130 } | 1127 } |
1131 case Token::OR: | 1128 case Token::OR: |
1132 case Token::AND: | 1129 case Token::AND: |
1133 FAIL(expr, "illegal logical operator"); | 1130 FAIL(expr, "illegal logical operator"); |
1134 case Token::BIT_OR: { | 1131 case Token::BIT_OR: { |
1135 // BIT_OR allows Any since it is used as a type coercion. | 1132 // BIT_OR allows Any since it is used as a type coercion. |
1136 VisitIntegerBitwiseOperator(expr, Type::Any(zone()), cache_.kAsmInt, | 1133 VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt, |
1137 cache_.kAsmSigned, true); | 1134 cache_.kAsmSigned, true); |
1138 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR) { | 1135 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR) { |
1139 expr->left()->set_bounds(Bounds(cache_.kAsmSigned)); | 1136 expr->left()->set_bounds(Bounds(cache_.kAsmSigned)); |
1140 } | 1137 } |
1141 return; | 1138 return; |
1142 } | 1139 } |
1143 case Token::BIT_XOR: { | 1140 case Token::BIT_XOR: { |
1144 // Handle booleans specially to handle de-sugared ! | 1141 // Handle booleans specially to handle de-sugared ! |
1145 Literal* left = expr->left()->AsLiteral(); | 1142 Literal* left = expr->left()->AsLiteral(); |
1146 if (left && left->value()->IsBoolean()) { | 1143 if (left && left->value()->IsBoolean()) { |
1147 if (left->ToBooleanIsTrue()) { | 1144 if (left->ToBooleanIsTrue()) { |
1148 left->set_bounds(Bounds(cache_.kSingletonOne)); | 1145 left->set_bounds(Bounds(cache_.kSingletonOne)); |
1149 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt, | 1146 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt, |
1150 "not operator expects an integer")); | 1147 "not operator expects an integer")); |
1151 IntersectResult(expr, cache_.kAsmSigned); | 1148 IntersectResult(expr, cache_.kAsmSigned); |
1152 return; | 1149 return; |
1153 } else { | 1150 } else { |
1154 FAIL(left, "unexpected false"); | 1151 FAIL(left, "unexpected false"); |
1155 } | 1152 } |
1156 } | 1153 } |
1157 // BIT_XOR allows Number since it is used as a type coercion (via ~~). | 1154 // BIT_XOR allows Number since it is used as a type coercion (via ~~). |
1158 VisitIntegerBitwiseOperator(expr, Type::Number(zone()), cache_.kAsmInt, | 1155 VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kAsmInt, |
1159 cache_.kAsmSigned, true); | 1156 cache_.kAsmSigned, true); |
1160 return; | 1157 return; |
1161 } | 1158 } |
1162 case Token::SHR: { | 1159 case Token::SHR: { |
1163 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, | 1160 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, |
1164 cache_.kAsmUnsigned, false); | 1161 cache_.kAsmUnsigned, false); |
1165 return; | 1162 return; |
1166 } | 1163 } |
1167 case Token::SHL: | 1164 case Token::SHL: |
1168 case Token::SAR: | 1165 case Token::SAR: |
1169 case Token::BIT_AND: { | 1166 case Token::BIT_AND: { |
1170 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, | 1167 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, |
1171 cache_.kAsmSigned, false); | 1168 cache_.kAsmSigned, false); |
1172 return; | 1169 return; |
1173 } | 1170 } |
1174 case Token::ADD: | 1171 case Token::ADD: |
1175 case Token::SUB: | 1172 case Token::SUB: |
1176 case Token::MUL: | 1173 case Token::MUL: |
1177 case Token::DIV: | 1174 case Token::DIV: |
1178 case Token::MOD: { | 1175 case Token::MOD: { |
1179 RECURSE(VisitWithExpectation( | 1176 RECURSE(VisitWithExpectation( |
1180 expr->left(), Type::Number(zone()), | 1177 expr->left(), Type::Number(), |
1181 "left arithmetic operand expected to be number")); | 1178 "left arithmetic operand expected to be number")); |
1182 Type* left_type = computed_type_; | 1179 Type* left_type = computed_type_; |
1183 int left_intish = intish_; | 1180 int left_intish = intish_; |
1184 RECURSE(VisitWithExpectation( | 1181 RECURSE(VisitWithExpectation( |
1185 expr->right(), Type::Number(zone()), | 1182 expr->right(), Type::Number(), |
1186 "right arithmetic operand expected to be number")); | 1183 "right arithmetic operand expected to be number")); |
1187 Type* right_type = computed_type_; | 1184 Type* right_type = computed_type_; |
1188 int right_intish = intish_; | 1185 int right_intish = intish_; |
1189 Type* type = Type::Union(left_type, right_type, zone()); | 1186 Type* type = Type::Union(left_type, right_type, zone()); |
1190 if (type->Is(cache_.kAsmInt)) { | 1187 if (type->Is(cache_.kAsmInt)) { |
1191 if (expr->op() == Token::MUL) { | 1188 if (expr->op() == Token::MUL) { |
1192 Literal* right = expr->right()->AsLiteral(); | 1189 Literal* right = expr->right()->AsLiteral(); |
1193 if (!right) { | 1190 if (!right) { |
1194 FAIL(expr, "direct integer multiply forbidden"); | 1191 FAIL(expr, "direct integer multiply forbidden"); |
1195 } | 1192 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1253 if (!in_function_) { | 1250 if (!in_function_) { |
1254 FAIL(expr, "comparison inside module body"); | 1251 FAIL(expr, "comparison inside module body"); |
1255 } | 1252 } |
1256 Token::Value op = expr->op(); | 1253 Token::Value op = expr->op(); |
1257 if (op != Token::EQ && op != Token::NE && op != Token::LT && | 1254 if (op != Token::EQ && op != Token::NE && op != Token::LT && |
1258 op != Token::LTE && op != Token::GT && op != Token::GTE) { | 1255 op != Token::LTE && op != Token::GT && op != Token::GTE) { |
1259 FAIL(expr, "illegal comparison operator"); | 1256 FAIL(expr, "illegal comparison operator"); |
1260 } | 1257 } |
1261 | 1258 |
1262 RECURSE( | 1259 RECURSE( |
1263 VisitWithExpectation(expr->left(), Type::Number(zone()), | 1260 VisitWithExpectation(expr->left(), Type::Number(), |
1264 "left comparison operand expected to be number")); | 1261 "left comparison operand expected to be number")); |
1265 Type* left_type = computed_type_; | 1262 Type* left_type = computed_type_; |
1266 if (!left_type->Is(cache_.kAsmComparable)) { | 1263 if (!left_type->Is(cache_.kAsmComparable)) { |
1267 FAIL(expr->left(), "bad type on left side of comparison"); | 1264 FAIL(expr->left(), "bad type on left side of comparison"); |
1268 } | 1265 } |
1269 | 1266 |
1270 RECURSE( | 1267 RECURSE( |
1271 VisitWithExpectation(expr->right(), Type::Number(zone()), | 1268 VisitWithExpectation(expr->right(), Type::Number(), |
1272 "right comparison operand expected to be number")); | 1269 "right comparison operand expected to be number")); |
1273 Type* right_type = computed_type_; | 1270 Type* right_type = computed_type_; |
1274 if (!right_type->Is(cache_.kAsmComparable)) { | 1271 if (!right_type->Is(cache_.kAsmComparable)) { |
1275 FAIL(expr->right(), "bad type on right side of comparison"); | 1272 FAIL(expr->right(), "bad type on right side of comparison"); |
1276 } | 1273 } |
1277 | 1274 |
1278 if (!left_type->Is(right_type) && !right_type->Is(left_type)) { | 1275 if (!left_type->Is(right_type) && !right_type->Is(left_type)) { |
1279 FAIL(expr, "left and right side of comparison must match"); | 1276 FAIL(expr, "left and right side of comparison must match"); |
1280 } | 1277 } |
1281 | 1278 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1320 | 1317 |
1321 | 1318 |
1322 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { | 1319 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { |
1323 FAIL(expr, "call reference not allowed"); | 1320 FAIL(expr, "call reference not allowed"); |
1324 } | 1321 } |
1325 | 1322 |
1326 | 1323 |
1327 void AsmTyper::InitializeStdlibSIMD() { | 1324 void AsmTyper::InitializeStdlibSIMD() { |
1328 #define V(NAME, Name, name, lane_count, lane_type) \ | 1325 #define V(NAME, Name, name, lane_count, lane_type) \ |
1329 { \ | 1326 { \ |
1330 Type* type = Type::Function(Type::Name(isolate_, zone()), \ | 1327 Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(), \ |
1331 Type::Any(zone()), lane_count, zone()); \ | 1328 lane_count, zone()); \ |
1332 for (int i = 0; i < lane_count; ++i) { \ | 1329 for (int i = 0; i < lane_count; ++i) { \ |
1333 type->AsFunction()->InitParameter(i, Type::Number(zone())); \ | 1330 type->AsFunction()->InitParameter(i, Type::Number()); \ |
1334 } \ | 1331 } \ |
1335 stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \ | 1332 stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \ |
1336 stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \ | 1333 stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \ |
1337 } | 1334 } |
1338 SIMD128_TYPES(V) | 1335 SIMD128_TYPES(V) |
1339 #undef V | 1336 #undef V |
1340 } | 1337 } |
1341 | 1338 |
1342 | 1339 |
1343 void AsmTyper::InitializeStdlib() { | 1340 void AsmTyper::InitializeStdlib() { |
1344 if (allow_simd_) { | 1341 if (allow_simd_) { |
1345 InitializeStdlibSIMD(); | 1342 InitializeStdlibSIMD(); |
1346 } | 1343 } |
1347 Type* number_type = Type::Number(zone()); | 1344 Type* number_type = Type::Number(); |
1348 Type* double_type = cache_.kAsmDouble; | 1345 Type* double_type = cache_.kAsmDouble; |
1349 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); | 1346 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); |
1350 Type* double_fn2_type = | 1347 Type* double_fn2_type = |
1351 Type::Function(double_type, double_type, double_type, zone()); | 1348 Type::Function(double_type, double_type, double_type, zone()); |
1352 | 1349 |
1353 Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone()); | 1350 Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone()); |
1354 Type* imul_type = | 1351 Type* imul_type = |
1355 Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone()); | 1352 Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone()); |
1356 // TODO(bradnelson): currently only approximating the proper intersection type | 1353 // TODO(bradnelson): currently only approximating the proper intersection type |
1357 // (which we cannot currently represent). | 1354 // (which we cannot currently represent). |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1394 for (unsigned i = 0; i < arraysize(math); ++i) { | 1391 for (unsigned i = 0; i < arraysize(math); ++i) { |
1395 stdlib_math_types_[math[i].name] = new (zone()) VariableInfo(math[i].type); | 1392 stdlib_math_types_[math[i].name] = new (zone()) VariableInfo(math[i].type); |
1396 stdlib_math_types_[math[i].name]->standard_member = math[i].standard_member; | 1393 stdlib_math_types_[math[i].name]->standard_member = math[i].standard_member; |
1397 } | 1394 } |
1398 stdlib_math_types_["fround"]->is_check_function = true; | 1395 stdlib_math_types_["fround"]->is_check_function = true; |
1399 | 1396 |
1400 stdlib_types_["Infinity"] = new (zone()) VariableInfo(double_type); | 1397 stdlib_types_["Infinity"] = new (zone()) VariableInfo(double_type); |
1401 stdlib_types_["Infinity"]->standard_member = kInfinity; | 1398 stdlib_types_["Infinity"]->standard_member = kInfinity; |
1402 stdlib_types_["NaN"] = new (zone()) VariableInfo(double_type); | 1399 stdlib_types_["NaN"] = new (zone()) VariableInfo(double_type); |
1403 stdlib_types_["NaN"]->standard_member = kNaN; | 1400 stdlib_types_["NaN"]->standard_member = kNaN; |
1404 Type* buffer_type = Type::Any(zone()); | 1401 Type* buffer_type = Type::Any(); |
1405 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ | 1402 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ |
1406 stdlib_types_[#TypeName "Array"] = new (zone()) VariableInfo( \ | 1403 stdlib_types_[#TypeName "Array"] = new (zone()) VariableInfo( \ |
1407 Type::Function(cache_.k##TypeName##Array, buffer_type, zone())); | 1404 Type::Function(cache_.k##TypeName##Array, buffer_type, zone())); |
1408 TYPED_ARRAYS(TYPED_ARRAY) | 1405 TYPED_ARRAYS(TYPED_ARRAY) |
1409 #undef TYPED_ARRAY | 1406 #undef TYPED_ARRAY |
1410 | 1407 |
1411 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ | 1408 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ |
1412 stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \ | 1409 stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \ |
1413 Type::Function(cache_.k##TypeName##Array, buffer_type, zone())); | 1410 Type::Function(cache_.k##TypeName##Array, buffer_type, zone())); |
1414 TYPED_ARRAYS(TYPED_ARRAY) | 1411 TYPED_ARRAYS(TYPED_ARRAY) |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1511 expr->set_bounds(Bounds(bounded_type)); | 1508 expr->set_bounds(Bounds(bounded_type)); |
1512 } | 1509 } |
1513 | 1510 |
1514 | 1511 |
1515 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type, | 1512 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type, |
1516 const char* msg) { | 1513 const char* msg) { |
1517 Type* save = expected_type_; | 1514 Type* save = expected_type_; |
1518 expected_type_ = expected_type; | 1515 expected_type_ = expected_type; |
1519 RECURSE(Visit(expr)); | 1516 RECURSE(Visit(expr)); |
1520 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); | 1517 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); |
1521 if (bounded_type->Is(Type::None(zone()))) { | 1518 if (bounded_type->Is(Type::None())) { |
1522 #ifdef DEBUG | 1519 #ifdef DEBUG |
1523 PrintF("Computed type: "); | 1520 PrintF("Computed type: "); |
1524 computed_type_->Print(); | 1521 computed_type_->Print(); |
1525 PrintF("Expected type: "); | 1522 PrintF("Expected type: "); |
1526 expected_type_->Print(); | 1523 expected_type_->Print(); |
1527 #endif | 1524 #endif |
1528 FAIL(expr, msg); | 1525 FAIL(expr, msg); |
1529 } | 1526 } |
1530 expected_type_ = save; | 1527 expected_type_ = save; |
1531 } | 1528 } |
1532 | 1529 |
1533 | 1530 |
1534 void AsmTyper::VisitRewritableAssignmentExpression( | 1531 void AsmTyper::VisitRewritableAssignmentExpression( |
1535 RewritableAssignmentExpression* expr) { | 1532 RewritableAssignmentExpression* expr) { |
1536 RECURSE(Visit(expr->expression())); | 1533 RECURSE(Visit(expr->expression())); |
1537 } | 1534 } |
1538 | 1535 |
1539 | 1536 |
1540 } // namespace internal | 1537 } // namespace internal |
1541 } // namespace v8 | 1538 } // namespace v8 |
OLD | NEW |