| 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/asmjs/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 |
| 11 #include "src/ast/ast.h" | 11 #include "src/ast/ast.h" |
| 12 #include "src/ast/scopes.h" | 12 #include "src/ast/scopes.h" |
| 13 #include "src/codegen.h" | 13 #include "src/codegen.h" |
| 14 #include "src/type-cache.h" | 14 #include "src/type-cache.h" |
| 15 | 15 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 36 } while (false) | 36 } while (false) |
| 37 | 37 |
| 38 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, | 38 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, |
| 39 FunctionLiteral* root) | 39 FunctionLiteral* root) |
| 40 : zone_(zone), | 40 : zone_(zone), |
| 41 isolate_(isolate), | 41 isolate_(isolate), |
| 42 script_(script), | 42 script_(script), |
| 43 root_(root), | 43 root_(root), |
| 44 valid_(true), | 44 valid_(true), |
| 45 allow_simd_(false), | 45 allow_simd_(false), |
| 46 fixed_signature_(false), |
| 46 property_info_(nullptr), | 47 property_info_(nullptr), |
| 47 intish_(0), | 48 intish_(0), |
| 48 stdlib_types_(zone), | 49 stdlib_types_(zone), |
| 49 stdlib_heap_types_(zone), | 50 stdlib_heap_types_(zone), |
| 50 stdlib_math_types_(zone), | 51 stdlib_math_types_(zone), |
| 51 #define V(NAME, Name, name, lane_count, lane_type) \ | 52 #define V(NAME, Name, name, lane_count, lane_type) \ |
| 52 stdlib_simd_##name##_types_(zone), | 53 stdlib_simd_##name##_types_(zone), |
| 53 SIMD128_TYPES(V) | 54 SIMD128_TYPES(V) |
| 54 #undef V | 55 #undef V |
| 55 global_variable_type_(base::HashMap::PointersMatch, | 56 global_variable_type_(base::HashMap::PointersMatch, |
| 56 ZoneHashMap::kDefaultHashMapCapacity, | 57 ZoneHashMap::kDefaultHashMapCapacity, |
| 57 ZoneAllocationPolicy(zone)), | 58 ZoneAllocationPolicy(zone)), |
| 58 local_variable_type_(base::HashMap::PointersMatch, | 59 local_variable_type_(base::HashMap::PointersMatch, |
| 59 ZoneHashMap::kDefaultHashMapCapacity, | 60 ZoneHashMap::kDefaultHashMapCapacity, |
| 60 ZoneAllocationPolicy(zone)), | 61 ZoneAllocationPolicy(zone)), |
| 61 in_function_(false), | 62 in_function_(false), |
| 62 building_function_tables_(false), | 63 building_function_tables_(false), |
| 63 visiting_exports_(false), | 64 visiting_exports_(false), |
| 64 cache_(TypeCache::Get()), | 65 cache_(TypeCache::Get()), |
| 65 bounds_(zone) { | 66 bounds_(zone) { |
| 66 InitializeAstVisitor(isolate); | 67 InitializeAstVisitor(isolate); |
| 67 InitializeStdlib(); | 68 InitializeStdlib(); |
| 68 } | 69 } |
| 69 | 70 |
| 70 | |
| 71 bool AsmTyper::Validate() { | 71 bool AsmTyper::Validate() { |
| 72 VisitAsmModule(root_); | 72 VisitAsmModule(root_); |
| 73 return valid_ && !HasStackOverflow(); | 73 return valid_ && !HasStackOverflow(); |
| 74 } | 74 } |
| 75 | 75 |
| 76 | |
| 77 void AsmTyper::VisitAsmModule(FunctionLiteral* fun) { | 76 void AsmTyper::VisitAsmModule(FunctionLiteral* fun) { |
| 78 Scope* scope = fun->scope(); | 77 Scope* scope = fun->scope(); |
| 79 if (!scope->is_function_scope()) FAIL(fun, "not at function scope"); | 78 if (!scope->is_function_scope()) FAIL(fun, "not at function scope"); |
| 80 | 79 |
| 81 ExpressionStatement* use_asm = fun->body()->first()->AsExpressionStatement(); | 80 ExpressionStatement* use_asm = fun->body()->first()->AsExpressionStatement(); |
| 82 if (use_asm == nullptr) FAIL(fun, "missing \"use asm\""); | 81 if (use_asm == nullptr) FAIL(fun, "missing \"use asm\""); |
| 83 Literal* use_asm_literal = use_asm->expression()->AsLiteral(); | 82 Literal* use_asm_literal = use_asm->expression()->AsLiteral(); |
| 84 if (use_asm_literal == nullptr) FAIL(fun, "missing \"use asm\""); | 83 if (use_asm_literal == nullptr) FAIL(fun, "missing \"use asm\""); |
| 85 if (!use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm")) | 84 if (!use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm")) |
| 86 FAIL(fun, "missing \"use asm\""); | 85 FAIL(fun, "missing \"use asm\""); |
| 87 | 86 |
| 87 // TODO(bradnelson): Generalize this. |
| 88 if (fixed_signature_ && scope->num_parameters() != 3) { |
| 89 FAIL(fun, |
| 90 "only asm modules with (stdlib, foreign, heap) " |
| 91 "parameters currently supported"); |
| 92 } |
| 93 |
| 88 // Module parameters. | 94 // Module parameters. |
| 89 for (int i = 0; i < scope->num_parameters(); ++i) { | 95 for (int i = 0; i < scope->num_parameters(); ++i) { |
| 90 Variable* param = scope->parameter(i); | 96 Variable* param = scope->parameter(i); |
| 91 DCHECK(GetType(param) == nullptr); | 97 DCHECK(GetType(param) == nullptr); |
| 92 SetType(param, Type::None()); | 98 SetType(param, Type::None()); |
| 93 } | 99 } |
| 94 | 100 |
| 95 ZoneList<Declaration*>* decls = scope->declarations(); | 101 ZoneList<Declaration*>* decls = scope->declarations(); |
| 96 | 102 |
| 97 // Set all globals to type Any. | 103 // Set all globals to type Any. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 // Validate exports. | 142 // Validate exports. |
| 137 visiting_exports_ = true; | 143 visiting_exports_ = true; |
| 138 ReturnStatement* stmt = fun->body()->last()->AsReturnStatement(); | 144 ReturnStatement* stmt = fun->body()->last()->AsReturnStatement(); |
| 139 if (stmt == nullptr) { | 145 if (stmt == nullptr) { |
| 140 FAIL(fun->body()->last(), "last statement in module is not a return"); | 146 FAIL(fun->body()->last(), "last statement in module is not a return"); |
| 141 } | 147 } |
| 142 RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(), | 148 RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(), |
| 143 "expected object export")); | 149 "expected object export")); |
| 144 } | 150 } |
| 145 | 151 |
| 146 | |
| 147 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) { | 152 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) { |
| 148 Variable* var = decl->proxy()->var(); | 153 Variable* var = decl->proxy()->var(); |
| 149 if (var->location() != VariableLocation::PARAMETER) { | 154 if (var->location() != VariableLocation::PARAMETER) { |
| 150 if (GetType(var) == nullptr) { | 155 if (GetType(var) == nullptr) { |
| 151 SetType(var, Type::Any()); | 156 SetType(var, Type::Any()); |
| 152 } else { | 157 } else { |
| 153 DCHECK(!GetType(var)->IsFunction()); | 158 DCHECK(!GetType(var)->IsFunction()); |
| 154 } | 159 } |
| 155 } | 160 } |
| 156 DCHECK(GetType(var) != nullptr); | 161 DCHECK(GetType(var) != nullptr); |
| 157 intish_ = 0; | 162 intish_ = 0; |
| 158 } | 163 } |
| 159 | 164 |
| 160 | |
| 161 void AsmTyper::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 165 void AsmTyper::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| 162 if (in_function_) { | 166 if (in_function_) { |
| 163 FAIL(decl, "function declared inside another"); | 167 FAIL(decl, "function declared inside another"); |
| 164 } | 168 } |
| 165 // Set function type so global references to functions have some type | 169 // Set function type so global references to functions have some type |
| 166 // (so they can give a more useful error). | 170 // (so they can give a more useful error). |
| 167 Variable* var = decl->proxy()->var(); | 171 Variable* var = decl->proxy()->var(); |
| 168 if (GetVariableInfo(var)) { | 172 if (GetVariableInfo(var)) { |
| 169 // Detect previously-seen functions. | 173 // Detect previously-seen functions. |
| 170 FAIL(decl->fun(), "function repeated in module"); | 174 FAIL(decl->fun(), "function repeated in module"); |
| 171 } | 175 } |
| 172 SetType(var, Type::Function()); | 176 SetType(var, Type::Function()); |
| 173 } | 177 } |
| 174 | 178 |
| 175 | |
| 176 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { | 179 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
| 177 // Extract result type. | 180 // Extract result type. |
| 178 ZoneList<Statement*>* body = fun->body(); | 181 ZoneList<Statement*>* body = fun->body(); |
| 179 Type* result_type = Type::Undefined(); | 182 Type* result_type = Type::Undefined(); |
| 180 if (body->length() > 0) { | 183 if (body->length() > 0) { |
| 181 ReturnStatement* stmt = body->last()->AsReturnStatement(); | 184 ReturnStatement* stmt = body->last()->AsReturnStatement(); |
| 182 if (stmt != nullptr) { | 185 if (stmt != nullptr) { |
| 183 Literal* literal = stmt->expression()->AsLiteral(); | 186 Literal* literal = stmt->expression()->AsLiteral(); |
| 184 Type* old_expected = expected_type_; | 187 Type* old_expected = expected_type_; |
| 185 expected_type_ = Type::Any(); | 188 expected_type_ = Type::Any(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 216 } | 219 } |
| 217 SetType(var, computed_type_); | 220 SetType(var, computed_type_); |
| 218 type->AsFunction()->InitParameter(i, computed_type_); | 221 type->AsFunction()->InitParameter(i, computed_type_); |
| 219 good = true; | 222 good = true; |
| 220 } | 223 } |
| 221 if (!good) FAIL(fun, "missing parameter type annotations"); | 224 if (!good) FAIL(fun, "missing parameter type annotations"); |
| 222 | 225 |
| 223 SetResult(fun, type); | 226 SetResult(fun, type); |
| 224 } | 227 } |
| 225 | 228 |
| 226 | |
| 227 void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, | 229 void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, |
| 228 bool is_return) { | 230 bool is_return) { |
| 229 // Normal +x or x|0 annotations. | 231 // Normal +x or x|0 annotations. |
| 230 BinaryOperation* bin = expr->AsBinaryOperation(); | 232 BinaryOperation* bin = expr->AsBinaryOperation(); |
| 231 if (bin != nullptr) { | 233 if (bin != nullptr) { |
| 232 if (var != nullptr) { | 234 if (var != nullptr) { |
| 233 VariableProxy* proxy = bin->left()->AsVariableProxy(); | 235 VariableProxy* proxy = bin->left()->AsVariableProxy(); |
| 234 if (proxy == nullptr) { | 236 if (proxy == nullptr) { |
| 235 FAIL(bin->left(), "expected variable for type annotation"); | 237 FAIL(bin->left(), "expected variable for type annotation"); |
| 236 } | 238 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 FAIL(call, "invalid argument count calling function"); | 298 FAIL(call, "invalid argument count calling function"); |
| 297 } | 299 } |
| 298 SetResult(expr, type->AsFunction()->Result()); | 300 SetResult(expr, type->AsFunction()->Result()); |
| 299 return; | 301 return; |
| 300 } | 302 } |
| 301 } | 303 } |
| 302 | 304 |
| 303 FAIL(expr, "invalid type annotation"); | 305 FAIL(expr, "invalid type annotation"); |
| 304 } | 306 } |
| 305 | 307 |
| 306 | |
| 307 void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) { | 308 void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) { |
| 308 for (int i = 0; i < stmts->length(); ++i) { | 309 for (int i = 0; i < stmts->length(); ++i) { |
| 309 Statement* stmt = stmts->at(i); | 310 Statement* stmt = stmts->at(i); |
| 310 RECURSE(Visit(stmt)); | 311 RECURSE(Visit(stmt)); |
| 311 } | 312 } |
| 312 } | 313 } |
| 313 | 314 |
| 314 | |
| 315 void AsmTyper::VisitBlock(Block* stmt) { | 315 void AsmTyper::VisitBlock(Block* stmt) { |
| 316 RECURSE(VisitStatements(stmt->statements())); | 316 RECURSE(VisitStatements(stmt->statements())); |
| 317 } | 317 } |
| 318 | 318 |
| 319 | |
| 320 void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) { | 319 void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 321 RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(), | 320 RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(), |
| 322 "expression statement expected to be any")); | 321 "expression statement expected to be any")); |
| 323 } | 322 } |
| 324 | 323 |
| 325 | |
| 326 void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {} | 324 void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {} |
| 327 | 325 |
| 328 | |
| 329 void AsmTyper::VisitSloppyBlockFunctionStatement( | 326 void AsmTyper::VisitSloppyBlockFunctionStatement( |
| 330 SloppyBlockFunctionStatement* stmt) { | 327 SloppyBlockFunctionStatement* stmt) { |
| 331 Visit(stmt->statement()); | 328 Visit(stmt->statement()); |
| 332 } | 329 } |
| 333 | 330 |
| 334 | |
| 335 void AsmTyper::VisitEmptyParentheses(EmptyParentheses* expr) { UNREACHABLE(); } | 331 void AsmTyper::VisitEmptyParentheses(EmptyParentheses* expr) { UNREACHABLE(); } |
| 336 | 332 |
| 337 | |
| 338 void AsmTyper::VisitIfStatement(IfStatement* stmt) { | 333 void AsmTyper::VisitIfStatement(IfStatement* stmt) { |
| 339 if (!in_function_) { | 334 if (!in_function_) { |
| 340 FAIL(stmt, "if statement inside module body"); | 335 FAIL(stmt, "if statement inside module body"); |
| 341 } | 336 } |
| 342 RECURSE(VisitWithExpectation(stmt->condition(), cache_.kAsmInt, | 337 RECURSE(VisitWithExpectation(stmt->condition(), cache_.kAsmInt, |
| 343 "if condition expected to be integer")); | 338 "if condition expected to be integer")); |
| 344 if (intish_ != 0) { | 339 if (intish_ != 0) { |
| 345 FAIL(stmt, "if condition expected to be signed or unsigned"); | 340 FAIL(stmt, "if condition expected to be signed or unsigned"); |
| 346 } | 341 } |
| 347 RECURSE(Visit(stmt->then_statement())); | 342 RECURSE(Visit(stmt->then_statement())); |
| 348 RECURSE(Visit(stmt->else_statement())); | 343 RECURSE(Visit(stmt->else_statement())); |
| 349 } | 344 } |
| 350 | 345 |
| 351 | |
| 352 void AsmTyper::VisitContinueStatement(ContinueStatement* stmt) { | 346 void AsmTyper::VisitContinueStatement(ContinueStatement* stmt) { |
| 353 if (!in_function_) { | 347 if (!in_function_) { |
| 354 FAIL(stmt, "continue statement inside module body"); | 348 FAIL(stmt, "continue statement inside module body"); |
| 355 } | 349 } |
| 356 } | 350 } |
| 357 | 351 |
| 358 | |
| 359 void AsmTyper::VisitBreakStatement(BreakStatement* stmt) { | 352 void AsmTyper::VisitBreakStatement(BreakStatement* stmt) { |
| 360 if (!in_function_) { | 353 if (!in_function_) { |
| 361 FAIL(stmt, "continue statement inside module body"); | 354 FAIL(stmt, "continue statement inside module body"); |
| 362 } | 355 } |
| 363 } | 356 } |
| 364 | 357 |
| 365 | |
| 366 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) { | 358 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) { |
| 367 // Handle module return statement in VisitAsmModule. | 359 // Handle module return statement in VisitAsmModule. |
| 368 if (!in_function_) { | 360 if (!in_function_) { |
| 369 return; | 361 return; |
| 370 } | 362 } |
| 371 Literal* literal = stmt->expression()->AsLiteral(); | 363 Literal* literal = stmt->expression()->AsLiteral(); |
| 372 if (literal) { | 364 if (literal) { |
| 373 VisitLiteral(literal, true); | 365 VisitLiteral(literal, true); |
| 374 } else { | 366 } else { |
| 375 RECURSE( | 367 RECURSE( |
| 376 VisitWithExpectation(stmt->expression(), Type::Any(), | 368 VisitWithExpectation(stmt->expression(), Type::Any(), |
| 377 "return expression expected to have return type")); | 369 "return expression expected to have return type")); |
| 378 } | 370 } |
| 379 if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) { | 371 if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) { |
| 380 FAIL(stmt->expression(), "return type does not match function signature"); | 372 FAIL(stmt->expression(), "return type does not match function signature"); |
| 381 } | 373 } |
| 382 } | 374 } |
| 383 | 375 |
| 384 | |
| 385 void AsmTyper::VisitWithStatement(WithStatement* stmt) { | 376 void AsmTyper::VisitWithStatement(WithStatement* stmt) { |
| 386 FAIL(stmt, "bad with statement"); | 377 FAIL(stmt, "bad with statement"); |
| 387 } | 378 } |
| 388 | 379 |
| 389 | |
| 390 void AsmTyper::VisitSwitchStatement(SwitchStatement* stmt) { | 380 void AsmTyper::VisitSwitchStatement(SwitchStatement* stmt) { |
| 391 if (!in_function_) { | 381 if (!in_function_) { |
| 392 FAIL(stmt, "switch statement inside module body"); | 382 FAIL(stmt, "switch statement inside module body"); |
| 393 } | 383 } |
| 394 RECURSE(VisitWithExpectation(stmt->tag(), cache_.kAsmSigned, | 384 RECURSE(VisitWithExpectation(stmt->tag(), cache_.kAsmSigned, |
| 395 "switch expression non-integer")); | 385 "switch expression non-integer")); |
| 396 ZoneList<CaseClause*>* clauses = stmt->cases(); | 386 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 397 ZoneSet<int32_t> cases(zone()); | 387 ZoneSet<int32_t> cases(zone()); |
| 398 for (int i = 0; i < clauses->length(); ++i) { | 388 for (int i = 0; i < clauses->length(); ++i) { |
| 399 CaseClause* clause = clauses->at(i); | 389 CaseClause* clause = clauses->at(i); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 420 } | 410 } |
| 421 if (cases.size() > 0) { | 411 if (cases.size() > 0) { |
| 422 int64_t min_case = *cases.begin(); | 412 int64_t min_case = *cases.begin(); |
| 423 int64_t max_case = *cases.rbegin(); | 413 int64_t max_case = *cases.rbegin(); |
| 424 if (max_case - min_case > std::numeric_limits<int32_t>::max()) { | 414 if (max_case - min_case > std::numeric_limits<int32_t>::max()) { |
| 425 FAIL(stmt, "case range too large"); | 415 FAIL(stmt, "case range too large"); |
| 426 } | 416 } |
| 427 } | 417 } |
| 428 } | 418 } |
| 429 | 419 |
| 430 | |
| 431 void AsmTyper::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } | 420 void AsmTyper::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } |
| 432 | 421 |
| 433 | |
| 434 void AsmTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { | 422 void AsmTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 435 if (!in_function_) { | 423 if (!in_function_) { |
| 436 FAIL(stmt, "do statement inside module body"); | 424 FAIL(stmt, "do statement inside module body"); |
| 437 } | 425 } |
| 438 RECURSE(Visit(stmt->body())); | 426 RECURSE(Visit(stmt->body())); |
| 439 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmInt, | 427 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmInt, |
| 440 "do condition expected to be integer")); | 428 "do condition expected to be integer")); |
| 441 if (intish_ != 0) { | 429 if (intish_ != 0) { |
| 442 FAIL(stmt, "do condition expected to be signed or unsigned"); | 430 FAIL(stmt, "do condition expected to be signed or unsigned"); |
| 443 } | 431 } |
| 444 } | 432 } |
| 445 | 433 |
| 446 | |
| 447 void AsmTyper::VisitWhileStatement(WhileStatement* stmt) { | 434 void AsmTyper::VisitWhileStatement(WhileStatement* stmt) { |
| 448 if (!in_function_) { | 435 if (!in_function_) { |
| 449 FAIL(stmt, "while statement inside module body"); | 436 FAIL(stmt, "while statement inside module body"); |
| 450 } | 437 } |
| 451 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmInt, | 438 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmInt, |
| 452 "while condition expected to be integer")); | 439 "while condition expected to be integer")); |
| 453 if (intish_ != 0) { | 440 if (intish_ != 0) { |
| 454 FAIL(stmt, "while condition expected to be signed or unsigned"); | 441 FAIL(stmt, "while condition expected to be signed or unsigned"); |
| 455 } | 442 } |
| 456 RECURSE(Visit(stmt->body())); | 443 RECURSE(Visit(stmt->body())); |
| 457 } | 444 } |
| 458 | 445 |
| 459 | |
| 460 void AsmTyper::VisitForStatement(ForStatement* stmt) { | 446 void AsmTyper::VisitForStatement(ForStatement* stmt) { |
| 461 if (!in_function_) { | 447 if (!in_function_) { |
| 462 FAIL(stmt, "for statement inside module body"); | 448 FAIL(stmt, "for statement inside module body"); |
| 463 } | 449 } |
| 464 if (stmt->init() != nullptr) { | 450 if (stmt->init() != nullptr) { |
| 465 RECURSE(Visit(stmt->init())); | 451 RECURSE(Visit(stmt->init())); |
| 466 } | 452 } |
| 467 if (stmt->cond() != nullptr) { | 453 if (stmt->cond() != nullptr) { |
| 468 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmInt, | 454 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmInt, |
| 469 "for condition expected to be integer")); | 455 "for condition expected to be integer")); |
| 470 } | 456 } |
| 471 if (intish_ != 0) { | 457 if (intish_ != 0) { |
| 472 FAIL(stmt, "for condition expected to be signed or unsigned"); | 458 FAIL(stmt, "for condition expected to be signed or unsigned"); |
| 473 } | 459 } |
| 474 if (stmt->next() != nullptr) { | 460 if (stmt->next() != nullptr) { |
| 475 RECURSE(Visit(stmt->next())); | 461 RECURSE(Visit(stmt->next())); |
| 476 } | 462 } |
| 477 RECURSE(Visit(stmt->body())); | 463 RECURSE(Visit(stmt->body())); |
| 478 } | 464 } |
| 479 | 465 |
| 480 | |
| 481 void AsmTyper::VisitForInStatement(ForInStatement* stmt) { | 466 void AsmTyper::VisitForInStatement(ForInStatement* stmt) { |
| 482 FAIL(stmt, "for-in statement encountered"); | 467 FAIL(stmt, "for-in statement encountered"); |
| 483 } | 468 } |
| 484 | 469 |
| 485 | |
| 486 void AsmTyper::VisitForOfStatement(ForOfStatement* stmt) { | 470 void AsmTyper::VisitForOfStatement(ForOfStatement* stmt) { |
| 487 FAIL(stmt, "for-of statement encountered"); | 471 FAIL(stmt, "for-of statement encountered"); |
| 488 } | 472 } |
| 489 | 473 |
| 490 | |
| 491 void AsmTyper::VisitTryCatchStatement(TryCatchStatement* stmt) { | 474 void AsmTyper::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 492 FAIL(stmt, "try statement encountered"); | 475 FAIL(stmt, "try statement encountered"); |
| 493 } | 476 } |
| 494 | 477 |
| 495 | |
| 496 void AsmTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 478 void AsmTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 497 FAIL(stmt, "try statement encountered"); | 479 FAIL(stmt, "try statement encountered"); |
| 498 } | 480 } |
| 499 | 481 |
| 500 | |
| 501 void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { | 482 void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 502 FAIL(stmt, "debugger statement encountered"); | 483 FAIL(stmt, "debugger statement encountered"); |
| 503 } | 484 } |
| 504 | 485 |
| 505 | |
| 506 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) { | 486 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 507 if (in_function_) { | 487 if (in_function_) { |
| 508 FAIL(expr, "invalid nested function"); | 488 FAIL(expr, "invalid nested function"); |
| 509 } | 489 } |
| 510 Scope* scope = expr->scope(); | 490 Scope* scope = expr->scope(); |
| 511 DCHECK(scope->is_function_scope()); | 491 DCHECK(scope->is_function_scope()); |
| 512 | 492 |
| 513 if (!bounds_.get(expr).upper->IsFunction()) { | 493 if (!bounds_.get(expr).upper->IsFunction()) { |
| 514 FAIL(expr, "invalid function literal"); | 494 FAIL(expr, "invalid function literal"); |
| 515 } | 495 } |
| 516 | 496 |
| 517 Type* type = bounds_.get(expr).upper; | 497 Type* type = bounds_.get(expr).upper; |
| 518 Type* save_return_type = return_type_; | 498 Type* save_return_type = return_type_; |
| 519 return_type_ = type->AsFunction()->Result(); | 499 return_type_ = type->AsFunction()->Result(); |
| 520 in_function_ = true; | 500 in_function_ = true; |
| 521 local_variable_type_.Clear(); | 501 local_variable_type_.Clear(); |
| 522 RECURSE(VisitDeclarations(scope->declarations())); | 502 RECURSE(VisitDeclarations(scope->declarations())); |
| 523 RECURSE(VisitStatements(expr->body())); | 503 RECURSE(VisitStatements(expr->body())); |
| 524 in_function_ = false; | 504 in_function_ = false; |
| 525 return_type_ = save_return_type; | 505 return_type_ = save_return_type; |
| 526 RECURSE(IntersectResult(expr, type)); | 506 RECURSE(IntersectResult(expr, type)); |
| 527 } | 507 } |
| 528 | 508 |
| 529 | |
| 530 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 509 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 531 FAIL(expr, "function info literal encountered"); | 510 FAIL(expr, "function info literal encountered"); |
| 532 } | 511 } |
| 533 | 512 |
| 534 | |
| 535 void AsmTyper::VisitDoExpression(DoExpression* expr) { | 513 void AsmTyper::VisitDoExpression(DoExpression* expr) { |
| 536 FAIL(expr, "do-expression encountered"); | 514 FAIL(expr, "do-expression encountered"); |
| 537 } | 515 } |
| 538 | 516 |
| 539 | |
| 540 void AsmTyper::VisitConditional(Conditional* expr) { | 517 void AsmTyper::VisitConditional(Conditional* expr) { |
| 541 if (!in_function_) { | 518 if (!in_function_) { |
| 542 FAIL(expr, "ternary operator inside module body"); | 519 FAIL(expr, "ternary operator inside module body"); |
| 543 } | 520 } |
| 544 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(), | 521 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(), |
| 545 "condition expected to be integer")); | 522 "condition expected to be integer")); |
| 546 if (!computed_type_->Is(cache_.kAsmInt)) { | 523 if (!computed_type_->Is(cache_.kAsmInt)) { |
| 547 FAIL(expr->condition(), "condition must be of type int"); | 524 FAIL(expr->condition(), "condition must be of type int"); |
| 548 } | 525 } |
| 549 | 526 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 565 (then_type->Is(cache_.kAsmDouble) && | 542 (then_type->Is(cache_.kAsmDouble) && |
| 566 else_type->Is(cache_.kAsmDouble)))) { | 543 else_type->Is(cache_.kAsmDouble)))) { |
| 567 FAIL(expr, | 544 FAIL(expr, |
| 568 "then and else expressions in ? must have the same type " | 545 "then and else expressions in ? must have the same type " |
| 569 "and be int, float, or double"); | 546 "and be int, float, or double"); |
| 570 } | 547 } |
| 571 | 548 |
| 572 RECURSE(IntersectResult(expr, then_type)); | 549 RECURSE(IntersectResult(expr, then_type)); |
| 573 } | 550 } |
| 574 | 551 |
| 575 | |
| 576 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { | 552 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { |
| 577 Variable* var = expr->var(); | 553 Variable* var = expr->var(); |
| 578 VariableInfo* info = GetVariableInfo(var); | 554 VariableInfo* info = GetVariableInfo(var); |
| 579 if (!in_function_ && !building_function_tables_ && !visiting_exports_) { | 555 if (!in_function_ && !building_function_tables_ && !visiting_exports_) { |
| 580 if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) { | 556 if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) { |
| 581 FAIL(expr, "illegal variable reference in module body"); | 557 FAIL(expr, "illegal variable reference in module body"); |
| 582 } | 558 } |
| 583 } | 559 } |
| 584 if (info == nullptr || info->type == nullptr) { | 560 if (info == nullptr || info->type == nullptr) { |
| 585 if (var->mode() == TEMPORARY) { | 561 if (var->mode() == TEMPORARY) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 } | 596 } |
| 621 } else if (!is_return && value->IsString()) { | 597 } else if (!is_return && value->IsString()) { |
| 622 RECURSE(IntersectResult(expr, Type::String())); | 598 RECURSE(IntersectResult(expr, Type::String())); |
| 623 } else if (value->IsUndefined(isolate_)) { | 599 } else if (value->IsUndefined(isolate_)) { |
| 624 RECURSE(IntersectResult(expr, Type::Undefined())); | 600 RECURSE(IntersectResult(expr, Type::Undefined())); |
| 625 } else { | 601 } else { |
| 626 FAIL(expr, "illegal literal"); | 602 FAIL(expr, "illegal literal"); |
| 627 } | 603 } |
| 628 } | 604 } |
| 629 | 605 |
| 630 | |
| 631 void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); } | 606 void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); } |
| 632 | 607 |
| 633 | |
| 634 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) { | 608 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 635 FAIL(expr, "regular expression encountered"); | 609 FAIL(expr, "regular expression encountered"); |
| 636 } | 610 } |
| 637 | 611 |
| 638 | |
| 639 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) { | 612 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) { |
| 640 if (in_function_) { | 613 if (in_function_) { |
| 641 FAIL(expr, "object literal in function"); | 614 FAIL(expr, "object literal in function"); |
| 642 } | 615 } |
| 643 // Allowed for asm module's export declaration. | 616 // Allowed for asm module's export declaration. |
| 644 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); | 617 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); |
| 645 for (int i = 0; i < props->length(); ++i) { | 618 for (int i = 0; i < props->length(); ++i) { |
| 646 ObjectLiteralProperty* prop = props->at(i); | 619 ObjectLiteralProperty* prop = props->at(i); |
| 647 RECURSE(VisitWithExpectation(prop->value(), Type::Any(), | 620 RECURSE(VisitWithExpectation(prop->value(), Type::Any(), |
| 648 "object property expected to be a function")); | 621 "object property expected to be a function")); |
| 649 if (!computed_type_->IsFunction()) { | 622 if (!computed_type_->IsFunction()) { |
| 650 FAIL(prop->value(), "non-function in function table"); | 623 FAIL(prop->value(), "non-function in function table"); |
| 651 } | 624 } |
| 652 } | 625 } |
| 653 RECURSE(IntersectResult(expr, Type::Object())); | 626 RECURSE(IntersectResult(expr, Type::Object())); |
| 654 } | 627 } |
| 655 | 628 |
| 656 | |
| 657 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) { | 629 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) { |
| 658 if (in_function_) { | 630 if (in_function_) { |
| 659 FAIL(expr, "array literal inside a function"); | 631 FAIL(expr, "array literal inside a function"); |
| 660 } | 632 } |
| 661 // Allowed for function tables. | 633 // Allowed for function tables. |
| 662 ZoneList<Expression*>* values = expr->values(); | 634 ZoneList<Expression*>* values = expr->values(); |
| 663 Type* elem_type = Type::None(); | 635 Type* elem_type = Type::None(); |
| 664 for (int i = 0; i < values->length(); ++i) { | 636 for (int i = 0; i < values->length(); ++i) { |
| 665 Expression* value = values->at(i); | 637 Expression* value = values->at(i); |
| 666 RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE")); | 638 RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE")); |
| 667 if (!computed_type_->IsFunction()) { | 639 if (!computed_type_->IsFunction()) { |
| 668 FAIL(value, "array component expected to be a function"); | 640 FAIL(value, "array component expected to be a function"); |
| 669 } | 641 } |
| 670 elem_type = Type::Union(elem_type, computed_type_, zone()); | 642 elem_type = Type::Union(elem_type, computed_type_, zone()); |
| 671 } | 643 } |
| 672 array_size_ = values->length(); | 644 array_size_ = values->length(); |
| 673 RECURSE(IntersectResult(expr, Type::Array(elem_type, zone()))); | 645 RECURSE(IntersectResult(expr, Type::Array(elem_type, zone()))); |
| 674 } | 646 } |
| 675 | 647 |
| 676 | |
| 677 void AsmTyper::VisitAssignment(Assignment* expr) { | 648 void AsmTyper::VisitAssignment(Assignment* expr) { |
| 678 // Handle function tables and everything else in different passes. | 649 // Handle function tables and everything else in different passes. |
| 679 if (!in_function_) { | 650 if (!in_function_) { |
| 680 if (expr->value()->IsArrayLiteral()) { | 651 if (expr->value()->IsArrayLiteral()) { |
| 681 if (!building_function_tables_) { | 652 if (!building_function_tables_) { |
| 682 return; | 653 return; |
| 683 } | 654 } |
| 684 } else { | 655 } else { |
| 685 if (building_function_tables_) { | 656 if (building_function_tables_) { |
| 686 return; | 657 return; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 FAIL(property->obj(), "array expected"); | 703 FAIL(property->obj(), "array expected"); |
| 733 } | 704 } |
| 734 if (value_intish != 0 && computed_type_->Is(cache_.kFloat64Array)) { | 705 if (value_intish != 0 && computed_type_->Is(cache_.kFloat64Array)) { |
| 735 FAIL(expr, "floatish assignment to double array"); | 706 FAIL(expr, "floatish assignment to double array"); |
| 736 } | 707 } |
| 737 VisitHeapAccess(property, true, target_type); | 708 VisitHeapAccess(property, true, target_type); |
| 738 } | 709 } |
| 739 RECURSE(IntersectResult(expr, target_type)); | 710 RECURSE(IntersectResult(expr, target_type)); |
| 740 } | 711 } |
| 741 | 712 |
| 742 | |
| 743 void AsmTyper::VisitYield(Yield* expr) { | 713 void AsmTyper::VisitYield(Yield* expr) { |
| 744 FAIL(expr, "yield expression encountered"); | 714 FAIL(expr, "yield expression encountered"); |
| 745 } | 715 } |
| 746 | 716 |
| 747 | |
| 748 void AsmTyper::VisitThrow(Throw* expr) { | 717 void AsmTyper::VisitThrow(Throw* expr) { |
| 749 FAIL(expr, "throw statement encountered"); | 718 FAIL(expr, "throw statement encountered"); |
| 750 } | 719 } |
| 751 | 720 |
| 752 | |
| 753 int AsmTyper::ElementShiftSize(Type* type) { | 721 int AsmTyper::ElementShiftSize(Type* type) { |
| 754 if (type->Is(cache_.kAsmSize8)) return 0; | 722 if (type->Is(cache_.kAsmSize8)) return 0; |
| 755 if (type->Is(cache_.kAsmSize16)) return 1; | 723 if (type->Is(cache_.kAsmSize16)) return 1; |
| 756 if (type->Is(cache_.kAsmSize32)) return 2; | 724 if (type->Is(cache_.kAsmSize32)) return 2; |
| 757 if (type->Is(cache_.kAsmSize64)) return 3; | 725 if (type->Is(cache_.kAsmSize64)) return 3; |
| 758 return -1; | 726 return -1; |
| 759 } | 727 } |
| 760 | 728 |
| 761 | |
| 762 Type* AsmTyper::StorageType(Type* type) { | 729 Type* AsmTyper::StorageType(Type* type) { |
| 763 if (type->Is(cache_.kAsmInt)) { | 730 if (type->Is(cache_.kAsmInt)) { |
| 764 return cache_.kAsmInt; | 731 return cache_.kAsmInt; |
| 765 } else { | 732 } else { |
| 766 return type; | 733 return type; |
| 767 } | 734 } |
| 768 } | 735 } |
| 769 | 736 |
| 770 | |
| 771 void AsmTyper::VisitHeapAccess(Property* expr, bool assigning, | 737 void AsmTyper::VisitHeapAccess(Property* expr, bool assigning, |
| 772 Type* assignment_type) { | 738 Type* assignment_type) { |
| 773 ArrayType* array_type = computed_type_->AsArray(); | 739 ArrayType* array_type = computed_type_->AsArray(); |
| 774 // size_t size = array_size_; | 740 // size_t size = array_size_; |
| 775 Type* type = array_type->Element(); | 741 Type* type = array_type->Element(); |
| 776 if (type->IsFunction()) { | 742 if (type->IsFunction()) { |
| 777 if (assigning) { | 743 if (assigning) { |
| 778 FAIL(expr, "assigning to function table is illegal"); | 744 FAIL(expr, "assigning to function table is illegal"); |
| 779 } | 745 } |
| 780 // TODO(bradnelson): Fix the parser and then un-comment this part | 746 // TODO(bradnelson): Fix the parser and then un-comment this part |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 if (!assignment_type->Is(result_type)) { | 820 if (!assignment_type->Is(result_type)) { |
| 855 FAIL(expr, "illegal type in assignment"); | 821 FAIL(expr, "illegal type in assignment"); |
| 856 } | 822 } |
| 857 } else { | 823 } else { |
| 858 RECURSE(IntersectResult(expr, expected_type_)); | 824 RECURSE(IntersectResult(expr, expected_type_)); |
| 859 RECURSE(IntersectResult(expr, result_type)); | 825 RECURSE(IntersectResult(expr, result_type)); |
| 860 } | 826 } |
| 861 } | 827 } |
| 862 } | 828 } |
| 863 | 829 |
| 864 | |
| 865 bool AsmTyper::IsStdlibObject(Expression* expr) { | 830 bool AsmTyper::IsStdlibObject(Expression* expr) { |
| 866 VariableProxy* proxy = expr->AsVariableProxy(); | 831 VariableProxy* proxy = expr->AsVariableProxy(); |
| 867 if (proxy == nullptr) { | 832 if (proxy == nullptr) { |
| 868 return false; | 833 return false; |
| 869 } | 834 } |
| 870 Variable* var = proxy->var(); | 835 Variable* var = proxy->var(); |
| 871 VariableInfo* info = GetVariableInfo(var); | 836 VariableInfo* info = GetVariableInfo(var); |
| 872 if (info) { | 837 if (info) { |
| 873 if (info->standard_member == kStdlib) return true; | 838 if (info->standard_member == kStdlib) return true; |
| 874 } | 839 } |
| 875 if (var->location() != VariableLocation::PARAMETER || var->index() != 0) { | 840 if (var->location() != VariableLocation::PARAMETER || var->index() != 0) { |
| 876 return false; | 841 return false; |
| 877 } | 842 } |
| 878 info = MakeVariableInfo(var); | 843 info = MakeVariableInfo(var); |
| 879 info->type = Type::Object(); | 844 info->type = Type::Object(); |
| 880 info->standard_member = kStdlib; | 845 info->standard_member = kStdlib; |
| 881 return true; | 846 return true; |
| 882 } | 847 } |
| 883 | 848 |
| 884 | |
| 885 Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr, | 849 Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr, |
| 886 const char* name) { | 850 const char* name) { |
| 887 Property* property = expr->AsProperty(); | 851 Property* property = expr->AsProperty(); |
| 888 if (property == nullptr) { | 852 if (property == nullptr) { |
| 889 return nullptr; | 853 return nullptr; |
| 890 } | 854 } |
| 891 Literal* key = property->key()->AsLiteral(); | 855 Literal* key = property->key()->AsLiteral(); |
| 892 if (key == nullptr || !key->IsPropertyName() || | 856 if (key == nullptr || !key->IsPropertyName() || |
| 893 !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) { | 857 !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) { |
| 894 return nullptr; | 858 return nullptr; |
| 895 } | 859 } |
| 896 return property->obj(); | 860 return property->obj(); |
| 897 } | 861 } |
| 898 | 862 |
| 899 | |
| 900 bool AsmTyper::IsMathObject(Expression* expr) { | 863 bool AsmTyper::IsMathObject(Expression* expr) { |
| 901 Expression* obj = GetReceiverOfPropertyAccess(expr, "Math"); | 864 Expression* obj = GetReceiverOfPropertyAccess(expr, "Math"); |
| 902 return obj && IsStdlibObject(obj); | 865 return obj && IsStdlibObject(obj); |
| 903 } | 866 } |
| 904 | 867 |
| 905 | |
| 906 bool AsmTyper::IsSIMDObject(Expression* expr) { | 868 bool AsmTyper::IsSIMDObject(Expression* expr) { |
| 907 Expression* obj = GetReceiverOfPropertyAccess(expr, "SIMD"); | 869 Expression* obj = GetReceiverOfPropertyAccess(expr, "SIMD"); |
| 908 return obj && IsStdlibObject(obj); | 870 return obj && IsStdlibObject(obj); |
| 909 } | 871 } |
| 910 | 872 |
| 911 | |
| 912 bool AsmTyper::IsSIMDTypeObject(Expression* expr, const char* name) { | 873 bool AsmTyper::IsSIMDTypeObject(Expression* expr, const char* name) { |
| 913 Expression* obj = GetReceiverOfPropertyAccess(expr, name); | 874 Expression* obj = GetReceiverOfPropertyAccess(expr, name); |
| 914 return obj && IsSIMDObject(obj); | 875 return obj && IsSIMDObject(obj); |
| 915 } | 876 } |
| 916 | 877 |
| 917 | |
| 918 void AsmTyper::VisitProperty(Property* expr) { | 878 void AsmTyper::VisitProperty(Property* expr) { |
| 919 if (IsMathObject(expr->obj())) { | 879 if (IsMathObject(expr->obj())) { |
| 920 VisitLibraryAccess(&stdlib_math_types_, expr); | 880 VisitLibraryAccess(&stdlib_math_types_, expr); |
| 921 return; | 881 return; |
| 922 } | 882 } |
| 923 #define V(NAME, Name, name, lane_count, lane_type) \ | 883 #define V(NAME, Name, name, lane_count, lane_type) \ |
| 924 if (IsSIMDTypeObject(expr->obj(), #Name)) { \ | 884 if (IsSIMDTypeObject(expr->obj(), #Name)) { \ |
| 925 VisitLibraryAccess(&stdlib_simd_##name##_types_, expr); \ | 885 VisitLibraryAccess(&stdlib_simd_##name##_types_, expr); \ |
| 926 return; \ | 886 return; \ |
| 927 } \ | 887 } \ |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1071 } | 1031 } |
| 1072 RECURSE(CheckPolymorphicStdlibArguments(standard_member, args)); | 1032 RECURSE(CheckPolymorphicStdlibArguments(standard_member, args)); |
| 1073 intish_ = 0; | 1033 intish_ = 0; |
| 1074 RECURSE(IntersectResult(expr, result_type)); | 1034 RECURSE(IntersectResult(expr, result_type)); |
| 1075 } | 1035 } |
| 1076 } else { | 1036 } else { |
| 1077 FAIL(expr, "invalid callee"); | 1037 FAIL(expr, "invalid callee"); |
| 1078 } | 1038 } |
| 1079 } | 1039 } |
| 1080 | 1040 |
| 1081 | |
| 1082 void AsmTyper::VisitCallNew(CallNew* expr) { | 1041 void AsmTyper::VisitCallNew(CallNew* expr) { |
| 1083 if (in_function_) { | 1042 if (in_function_) { |
| 1084 FAIL(expr, "new not allowed in module function"); | 1043 FAIL(expr, "new not allowed in module function"); |
| 1085 } | 1044 } |
| 1086 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), | 1045 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), |
| 1087 "expected stdlib function")); | 1046 "expected stdlib function")); |
| 1088 if (computed_type_->IsFunction()) { | 1047 if (computed_type_->IsFunction()) { |
| 1089 FunctionType* fun_type = computed_type_->AsFunction(); | 1048 FunctionType* fun_type = computed_type_->AsFunction(); |
| 1090 ZoneList<Expression*>* args = expr->arguments(); | 1049 ZoneList<Expression*>* args = expr->arguments(); |
| 1091 if (fun_type->Arity() != args->length()) | 1050 if (fun_type->Arity() != args->length()) |
| 1092 FAIL(expr, "call with wrong arity"); | 1051 FAIL(expr, "call with wrong arity"); |
| 1093 for (int i = 0; i < args->length(); ++i) { | 1052 for (int i = 0; i < args->length(); ++i) { |
| 1094 Expression* arg = args->at(i); | 1053 Expression* arg = args->at(i); |
| 1095 RECURSE(VisitWithExpectation( | 1054 RECURSE(VisitWithExpectation( |
| 1096 arg, fun_type->Parameter(i), | 1055 arg, fun_type->Parameter(i), |
| 1097 "constructor argument expected to match callee parameter")); | 1056 "constructor argument expected to match callee parameter")); |
| 1098 } | 1057 } |
| 1099 RECURSE(IntersectResult(expr, fun_type->Result())); | 1058 RECURSE(IntersectResult(expr, fun_type->Result())); |
| 1100 return; | 1059 return; |
| 1101 } | 1060 } |
| 1102 | 1061 |
| 1103 FAIL(expr, "ill-typed new operator"); | 1062 FAIL(expr, "ill-typed new operator"); |
| 1104 } | 1063 } |
| 1105 | 1064 |
| 1106 | |
| 1107 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { | 1065 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { |
| 1108 FAIL(expr, "runtime call not allowed"); | 1066 FAIL(expr, "runtime call not allowed"); |
| 1109 } | 1067 } |
| 1110 | 1068 |
| 1111 | |
| 1112 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { | 1069 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { |
| 1113 if (!in_function_) { | 1070 if (!in_function_) { |
| 1114 FAIL(expr, "unary operator inside module body"); | 1071 FAIL(expr, "unary operator inside module body"); |
| 1115 } | 1072 } |
| 1116 switch (expr->op()) { | 1073 switch (expr->op()) { |
| 1117 case Token::NOT: // Used to encode != and !== | 1074 case Token::NOT: // Used to encode != and !== |
| 1118 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, | 1075 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, |
| 1119 "operand expected to be integer")); | 1076 "operand expected to be integer")); |
| 1120 RECURSE(IntersectResult(expr, cache_.kAsmSigned)); | 1077 RECURSE(IntersectResult(expr, cache_.kAsmSigned)); |
| 1121 return; | 1078 return; |
| 1122 case Token::DELETE: | 1079 case Token::DELETE: |
| 1123 FAIL(expr, "delete operator encountered"); | 1080 FAIL(expr, "delete operator encountered"); |
| 1124 case Token::VOID: | 1081 case Token::VOID: |
| 1125 FAIL(expr, "void operator encountered"); | 1082 FAIL(expr, "void operator encountered"); |
| 1126 case Token::TYPEOF: | 1083 case Token::TYPEOF: |
| 1127 FAIL(expr, "typeof operator encountered"); | 1084 FAIL(expr, "typeof operator encountered"); |
| 1128 default: | 1085 default: |
| 1129 UNREACHABLE(); | 1086 UNREACHABLE(); |
| 1130 } | 1087 } |
| 1131 } | 1088 } |
| 1132 | 1089 |
| 1133 | |
| 1134 void AsmTyper::VisitCountOperation(CountOperation* expr) { | 1090 void AsmTyper::VisitCountOperation(CountOperation* expr) { |
| 1135 FAIL(expr, "increment or decrement operator encountered"); | 1091 FAIL(expr, "increment or decrement operator encountered"); |
| 1136 } | 1092 } |
| 1137 | 1093 |
| 1138 | |
| 1139 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, | 1094 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, |
| 1140 Type* left_expected, | 1095 Type* left_expected, |
| 1141 Type* right_expected, | 1096 Type* right_expected, |
| 1142 Type* result_type, bool conversion) { | 1097 Type* result_type, bool conversion) { |
| 1143 RECURSE(VisitWithExpectation(expr->left(), Type::Number(), | 1098 RECURSE(VisitWithExpectation(expr->left(), Type::Number(), |
| 1144 "left bitwise operand expected to be a number")); | 1099 "left bitwise operand expected to be a number")); |
| 1145 int32_t left_intish = intish_; | 1100 int32_t left_intish = intish_; |
| 1146 Type* left_type = computed_type_; | 1101 Type* left_type = computed_type_; |
| 1147 if (!left_type->Is(left_expected)) { | 1102 if (!left_type->Is(left_expected)) { |
| 1148 FAIL(expr->left(), "left bitwise operand expected to be an integer"); | 1103 FAIL(expr->left(), "left bitwise operand expected to be an integer"); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1172 right_type = left_type; | 1127 right_type = left_type; |
| 1173 } | 1128 } |
| 1174 if (!conversion) { | 1129 if (!conversion) { |
| 1175 if (!left_type->Is(cache_.kAsmIntQ) || !right_type->Is(cache_.kAsmIntQ)) { | 1130 if (!left_type->Is(cache_.kAsmIntQ) || !right_type->Is(cache_.kAsmIntQ)) { |
| 1176 FAIL(expr, "ill-typed bitwise operation"); | 1131 FAIL(expr, "ill-typed bitwise operation"); |
| 1177 } | 1132 } |
| 1178 } | 1133 } |
| 1179 RECURSE(IntersectResult(expr, result_type)); | 1134 RECURSE(IntersectResult(expr, result_type)); |
| 1180 } | 1135 } |
| 1181 | 1136 |
| 1182 | |
| 1183 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { | 1137 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
| 1184 if (!in_function_) { | 1138 if (!in_function_) { |
| 1185 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) { | 1139 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) { |
| 1186 FAIL(expr, "illegal binary operator inside module body"); | 1140 FAIL(expr, "illegal binary operator inside module body"); |
| 1187 } | 1141 } |
| 1188 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) || | 1142 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) || |
| 1189 !expr->right()->IsLiteral()) { | 1143 !expr->right()->IsLiteral()) { |
| 1190 FAIL(expr, "illegal computation inside module body"); | 1144 FAIL(expr, "illegal computation inside module body"); |
| 1191 } | 1145 } |
| 1192 DCHECK(expr->right()->AsLiteral() != nullptr); | 1146 DCHECK(expr->right()->AsLiteral() != nullptr); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1370 return; | 1324 return; |
| 1371 } else { | 1325 } else { |
| 1372 FAIL(expr, "ill-typed arithmetic operation"); | 1326 FAIL(expr, "ill-typed arithmetic operation"); |
| 1373 } | 1327 } |
| 1374 } | 1328 } |
| 1375 default: | 1329 default: |
| 1376 UNREACHABLE(); | 1330 UNREACHABLE(); |
| 1377 } | 1331 } |
| 1378 } | 1332 } |
| 1379 | 1333 |
| 1380 | |
| 1381 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { | 1334 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { |
| 1382 if (!in_function_) { | 1335 if (!in_function_) { |
| 1383 FAIL(expr, "comparison inside module body"); | 1336 FAIL(expr, "comparison inside module body"); |
| 1384 } | 1337 } |
| 1385 Token::Value op = expr->op(); | 1338 Token::Value op = expr->op(); |
| 1386 if (op != Token::EQ && op != Token::NE && op != Token::LT && | 1339 if (op != Token::EQ && op != Token::NE && op != Token::LT && |
| 1387 op != Token::LTE && op != Token::GT && op != Token::GTE) { | 1340 op != Token::LTE && op != Token::GT && op != Token::GTE) { |
| 1388 FAIL(expr, "illegal comparison operator"); | 1341 FAIL(expr, "illegal comparison operator"); |
| 1389 } | 1342 } |
| 1390 | 1343 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1409 (left_type->Is(cache_.kAsmDouble) && | 1362 (left_type->Is(cache_.kAsmDouble) && |
| 1410 right_type->Is(cache_.kAsmDouble)))) { | 1363 right_type->Is(cache_.kAsmDouble)))) { |
| 1411 FAIL(expr, | 1364 FAIL(expr, |
| 1412 "left and right side of comparison must match type " | 1365 "left and right side of comparison must match type " |
| 1413 "and be signed, unsigned, float, or double"); | 1366 "and be signed, unsigned, float, or double"); |
| 1414 } | 1367 } |
| 1415 | 1368 |
| 1416 RECURSE(IntersectResult(expr, cache_.kAsmSigned)); | 1369 RECURSE(IntersectResult(expr, cache_.kAsmSigned)); |
| 1417 } | 1370 } |
| 1418 | 1371 |
| 1419 | |
| 1420 void AsmTyper::VisitThisFunction(ThisFunction* expr) { | 1372 void AsmTyper::VisitThisFunction(ThisFunction* expr) { |
| 1421 FAIL(expr, "this function not allowed"); | 1373 FAIL(expr, "this function not allowed"); |
| 1422 } | 1374 } |
| 1423 | 1375 |
| 1424 | |
| 1425 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { | 1376 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { |
| 1426 for (int i = 0; i < decls->length(); ++i) { | 1377 for (int i = 0; i < decls->length(); ++i) { |
| 1427 Declaration* decl = decls->at(i); | 1378 Declaration* decl = decls->at(i); |
| 1428 RECURSE(Visit(decl)); | 1379 RECURSE(Visit(decl)); |
| 1429 } | 1380 } |
| 1430 } | 1381 } |
| 1431 | 1382 |
| 1432 | |
| 1433 void AsmTyper::VisitImportDeclaration(ImportDeclaration* decl) { | 1383 void AsmTyper::VisitImportDeclaration(ImportDeclaration* decl) { |
| 1434 FAIL(decl, "import declaration encountered"); | 1384 FAIL(decl, "import declaration encountered"); |
| 1435 } | 1385 } |
| 1436 | 1386 |
| 1437 | |
| 1438 void AsmTyper::VisitClassLiteral(ClassLiteral* expr) { | 1387 void AsmTyper::VisitClassLiteral(ClassLiteral* expr) { |
| 1439 FAIL(expr, "class literal not allowed"); | 1388 FAIL(expr, "class literal not allowed"); |
| 1440 } | 1389 } |
| 1441 | 1390 |
| 1442 | |
| 1443 void AsmTyper::VisitSpread(Spread* expr) { FAIL(expr, "spread not allowed"); } | 1391 void AsmTyper::VisitSpread(Spread* expr) { FAIL(expr, "spread not allowed"); } |
| 1444 | 1392 |
| 1445 | |
| 1446 void AsmTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) { | 1393 void AsmTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) { |
| 1447 FAIL(expr, "super property reference not allowed"); | 1394 FAIL(expr, "super property reference not allowed"); |
| 1448 } | 1395 } |
| 1449 | 1396 |
| 1450 | |
| 1451 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { | 1397 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { |
| 1452 FAIL(expr, "call reference not allowed"); | 1398 FAIL(expr, "call reference not allowed"); |
| 1453 } | 1399 } |
| 1454 | 1400 |
| 1455 | |
| 1456 void AsmTyper::InitializeStdlibSIMD() { | 1401 void AsmTyper::InitializeStdlibSIMD() { |
| 1457 #define V(NAME, Name, name, lane_count, lane_type) \ | 1402 #define V(NAME, Name, name, lane_count, lane_type) \ |
| 1458 { \ | 1403 { \ |
| 1459 Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(), \ | 1404 Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(), \ |
| 1460 lane_count, zone()); \ | 1405 lane_count, zone()); \ |
| 1461 for (int i = 0; i < lane_count; ++i) { \ | 1406 for (int i = 0; i < lane_count; ++i) { \ |
| 1462 type->AsFunction()->InitParameter(i, Type::Number()); \ | 1407 type->AsFunction()->InitParameter(i, Type::Number()); \ |
| 1463 } \ | 1408 } \ |
| 1464 stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \ | 1409 stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \ |
| 1465 stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \ | 1410 stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \ |
| 1466 } | 1411 } |
| 1467 SIMD128_TYPES(V) | 1412 SIMD128_TYPES(V) |
| 1468 #undef V | 1413 #undef V |
| 1469 } | 1414 } |
| 1470 | 1415 |
| 1471 | |
| 1472 void AsmTyper::InitializeStdlib() { | 1416 void AsmTyper::InitializeStdlib() { |
| 1473 if (allow_simd_) { | 1417 if (allow_simd_) { |
| 1474 InitializeStdlibSIMD(); | 1418 InitializeStdlibSIMD(); |
| 1475 } | 1419 } |
| 1476 Type* number_type = Type::Number(); | 1420 Type* number_type = Type::Number(); |
| 1477 Type* double_type = cache_.kAsmDouble; | 1421 Type* double_type = cache_.kAsmDouble; |
| 1478 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); | 1422 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); |
| 1479 Type* double_fn2_type = | 1423 Type* double_fn2_type = |
| 1480 Type::Function(double_type, double_type, double_type, zone()); | 1424 Type::Function(double_type, double_type, double_type, zone()); |
| 1481 | 1425 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1537 TYPED_ARRAYS(TYPED_ARRAY) | 1481 TYPED_ARRAYS(TYPED_ARRAY) |
| 1538 #undef TYPED_ARRAY | 1482 #undef TYPED_ARRAY |
| 1539 | 1483 |
| 1540 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ | 1484 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ |
| 1541 stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \ | 1485 stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \ |
| 1542 Type::Function(cache_.k##TypeName##Array, buffer_type, zone())); | 1486 Type::Function(cache_.k##TypeName##Array, buffer_type, zone())); |
| 1543 TYPED_ARRAYS(TYPED_ARRAY) | 1487 TYPED_ARRAYS(TYPED_ARRAY) |
| 1544 #undef TYPED_ARRAY | 1488 #undef TYPED_ARRAY |
| 1545 } | 1489 } |
| 1546 | 1490 |
| 1547 | |
| 1548 void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) { | 1491 void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) { |
| 1549 Literal* key = expr->key()->AsLiteral(); | 1492 Literal* key = expr->key()->AsLiteral(); |
| 1550 if (key == nullptr || !key->IsPropertyName()) | 1493 if (key == nullptr || !key->IsPropertyName()) |
| 1551 FAIL(expr, "invalid key used on stdlib member"); | 1494 FAIL(expr, "invalid key used on stdlib member"); |
| 1552 Handle<String> name = key->AsPropertyName(); | 1495 Handle<String> name = key->AsPropertyName(); |
| 1553 VariableInfo* info = LibType(map, name); | 1496 VariableInfo* info = LibType(map, name); |
| 1554 if (info == nullptr || info->type == nullptr) | 1497 if (info == nullptr || info->type == nullptr) |
| 1555 FAIL(expr, "unknown stdlib function"); | 1498 FAIL(expr, "unknown stdlib function"); |
| 1556 SetResult(expr, info->type); | 1499 SetResult(expr, info->type); |
| 1557 property_info_ = info; | 1500 property_info_ = info; |
| 1558 } | 1501 } |
| 1559 | 1502 |
| 1560 | |
| 1561 AsmTyper::VariableInfo* AsmTyper::LibType(ObjectTypeMap* map, | 1503 AsmTyper::VariableInfo* AsmTyper::LibType(ObjectTypeMap* map, |
| 1562 Handle<String> name) { | 1504 Handle<String> name) { |
| 1563 base::SmartArrayPointer<char> aname = name->ToCString(); | 1505 base::SmartArrayPointer<char> aname = name->ToCString(); |
| 1564 ObjectTypeMap::iterator i = map->find(std::string(aname.get())); | 1506 ObjectTypeMap::iterator i = map->find(std::string(aname.get())); |
| 1565 if (i == map->end()) { | 1507 if (i == map->end()) { |
| 1566 return nullptr; | 1508 return nullptr; |
| 1567 } | 1509 } |
| 1568 return i->second; | 1510 return i->second; |
| 1569 } | 1511 } |
| 1570 | 1512 |
| 1571 | |
| 1572 void AsmTyper::SetType(Variable* variable, Type* type) { | 1513 void AsmTyper::SetType(Variable* variable, Type* type) { |
| 1573 VariableInfo* info = MakeVariableInfo(variable); | 1514 VariableInfo* info = MakeVariableInfo(variable); |
| 1574 info->type = type; | 1515 info->type = type; |
| 1575 } | 1516 } |
| 1576 | 1517 |
| 1577 | |
| 1578 Type* AsmTyper::GetType(Variable* variable) { | 1518 Type* AsmTyper::GetType(Variable* variable) { |
| 1579 VariableInfo* info = GetVariableInfo(variable); | 1519 VariableInfo* info = GetVariableInfo(variable); |
| 1580 if (!info) return nullptr; | 1520 if (!info) return nullptr; |
| 1581 return info->type; | 1521 return info->type; |
| 1582 } | 1522 } |
| 1583 | 1523 |
| 1584 AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable) { | 1524 AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable) { |
| 1585 ZoneHashMap* map = | 1525 ZoneHashMap* map = |
| 1586 in_function_ ? &local_variable_type_ : &global_variable_type_; | 1526 in_function_ ? &local_variable_type_ : &global_variable_type_; |
| 1587 ZoneHashMap::Entry* entry = | 1527 ZoneHashMap::Entry* entry = |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1603 } | 1543 } |
| 1604 | 1544 |
| 1605 void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) { | 1545 void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) { |
| 1606 VariableInfo* dest = MakeVariableInfo(variable); | 1546 VariableInfo* dest = MakeVariableInfo(variable); |
| 1607 dest->type = info->type; | 1547 dest->type = info->type; |
| 1608 dest->is_check_function = info->is_check_function; | 1548 dest->is_check_function = info->is_check_function; |
| 1609 dest->is_constructor_function = info->is_constructor_function; | 1549 dest->is_constructor_function = info->is_constructor_function; |
| 1610 dest->standard_member = info->standard_member; | 1550 dest->standard_member = info->standard_member; |
| 1611 } | 1551 } |
| 1612 | 1552 |
| 1613 | |
| 1614 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember( | 1553 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember( |
| 1615 Variable* variable) { | 1554 Variable* variable) { |
| 1616 VariableInfo* info = GetVariableInfo(variable); | 1555 VariableInfo* info = GetVariableInfo(variable); |
| 1617 if (!info) return kNone; | 1556 if (!info) return kNone; |
| 1618 return info->standard_member; | 1557 return info->standard_member; |
| 1619 } | 1558 } |
| 1620 | 1559 |
| 1621 | |
| 1622 void AsmTyper::SetResult(Expression* expr, Type* type) { | 1560 void AsmTyper::SetResult(Expression* expr, Type* type) { |
| 1623 computed_type_ = type; | 1561 computed_type_ = type; |
| 1624 bounds_.set(expr, Bounds(computed_type_)); | 1562 bounds_.set(expr, Bounds(computed_type_)); |
| 1625 } | 1563 } |
| 1626 | 1564 |
| 1627 | |
| 1628 void AsmTyper::IntersectResult(Expression* expr, Type* type) { | 1565 void AsmTyper::IntersectResult(Expression* expr, Type* type) { |
| 1629 computed_type_ = type; | 1566 computed_type_ = type; |
| 1630 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); | 1567 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); |
| 1631 if (Type::Representation(bounded_type, zone())->Is(Type::None())) { | 1568 if (Type::Representation(bounded_type, zone())->Is(Type::None())) { |
| 1632 #ifdef DEBUG | 1569 #ifdef DEBUG |
| 1633 PrintF("Computed type: "); | 1570 PrintF("Computed type: "); |
| 1634 computed_type_->Print(); | 1571 computed_type_->Print(); |
| 1635 PrintF("Expected type: "); | 1572 PrintF("Expected type: "); |
| 1636 expected_type_->Print(); | 1573 expected_type_->Print(); |
| 1637 #endif | 1574 #endif |
| 1638 FAIL(expr, "type mismatch"); | 1575 FAIL(expr, "type mismatch"); |
| 1639 } | 1576 } |
| 1640 bounds_.set(expr, Bounds(bounded_type)); | 1577 bounds_.set(expr, Bounds(bounded_type)); |
| 1641 } | 1578 } |
| 1642 | 1579 |
| 1643 | |
| 1644 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type, | 1580 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type, |
| 1645 const char* msg) { | 1581 const char* msg) { |
| 1646 Type* save = expected_type_; | 1582 Type* save = expected_type_; |
| 1647 expected_type_ = expected_type; | 1583 expected_type_ = expected_type; |
| 1648 RECURSE(Visit(expr)); | 1584 RECURSE(Visit(expr)); |
| 1649 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); | 1585 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); |
| 1650 if (Type::Representation(bounded_type, zone())->Is(Type::None())) { | 1586 if (Type::Representation(bounded_type, zone())->Is(Type::None())) { |
| 1651 #ifdef DEBUG | 1587 #ifdef DEBUG |
| 1652 PrintF("Computed type: "); | 1588 PrintF("Computed type: "); |
| 1653 computed_type_->Print(); | 1589 computed_type_->Print(); |
| 1654 PrintF("Expected type: "); | 1590 PrintF("Expected type: "); |
| 1655 expected_type_->Print(); | 1591 expected_type_->Print(); |
| 1656 #endif | 1592 #endif |
| 1657 FAIL(expr, msg); | 1593 FAIL(expr, msg); |
| 1658 } | 1594 } |
| 1659 expected_type_ = save; | 1595 expected_type_ = save; |
| 1660 } | 1596 } |
| 1661 | 1597 |
| 1662 | |
| 1663 void AsmTyper::VisitRewritableExpression(RewritableExpression* expr) { | 1598 void AsmTyper::VisitRewritableExpression(RewritableExpression* expr) { |
| 1664 RECURSE(Visit(expr->expression())); | 1599 RECURSE(Visit(expr->expression())); |
| 1665 } | 1600 } |
| 1666 | 1601 |
| 1667 | |
| 1668 } // namespace internal | 1602 } // namespace internal |
| 1669 } // namespace v8 | 1603 } // namespace v8 |
| OLD | NEW |