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 |