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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/typing-asm.h" | 7 #include "src/typing-asm.h" |
8 | 8 |
9 #include "src/ast.h" | 9 #include "src/ast.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 } | 142 } |
143 | 143 |
144 | 144 |
145 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { | 145 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
146 // Extract result type. | 146 // Extract result type. |
147 ZoneList<Statement*>* body = fun->body(); | 147 ZoneList<Statement*>* body = fun->body(); |
148 Type* result_type = Type::Undefined(zone()); | 148 Type* result_type = Type::Undefined(zone()); |
149 if (body->length() > 0) { | 149 if (body->length() > 0) { |
150 ReturnStatement* stmt = body->last()->AsReturnStatement(); | 150 ReturnStatement* stmt = body->last()->AsReturnStatement(); |
151 if (stmt != NULL) { | 151 if (stmt != NULL) { |
152 RECURSE(VisitExpressionAnnotation(stmt->expression())); | 152 Literal* literal = stmt->expression()->AsLiteral(); |
| 153 Type* old_expected = expected_type_; |
| 154 expected_type_ = Type::Any(); |
| 155 if (literal) { |
| 156 RECURSE(VisitLiteral(literal, true)); |
| 157 } else { |
| 158 RECURSE(VisitExpressionAnnotation(stmt->expression(), true)); |
| 159 } |
| 160 expected_type_ = old_expected; |
153 result_type = computed_type_; | 161 result_type = computed_type_; |
154 } | 162 } |
155 } | 163 } |
156 Type::FunctionType* type = | 164 Type::FunctionType* type = |
157 Type::Function(result_type, Type::Any(), fun->parameter_count(), zone()) | 165 Type::Function(result_type, Type::Any(), fun->parameter_count(), zone()) |
158 ->AsFunction(); | 166 ->AsFunction(); |
159 | 167 |
160 // Extract parameter types. | 168 // Extract parameter types. |
161 bool good = true; | 169 bool good = true; |
162 for (int i = 0; i < fun->parameter_count(); ++i) { | 170 for (int i = 0; i < fun->parameter_count(); ++i) { |
163 good = false; | 171 good = false; |
164 if (i >= body->length()) break; | 172 if (i >= body->length()) break; |
165 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement(); | 173 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement(); |
166 if (stmt == NULL) break; | 174 if (stmt == NULL) break; |
167 Assignment* expr = stmt->expression()->AsAssignment(); | 175 Assignment* expr = stmt->expression()->AsAssignment(); |
168 if (expr == NULL || expr->is_compound()) break; | 176 if (expr == NULL || expr->is_compound()) break; |
169 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 177 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
170 if (proxy == NULL) break; | 178 if (proxy == NULL) break; |
171 Variable* var = proxy->var(); | 179 Variable* var = proxy->var(); |
172 if (var->location() != VariableLocation::PARAMETER || var->index() != i) | 180 if (var->location() != VariableLocation::PARAMETER || var->index() != i) |
173 break; | 181 break; |
174 RECURSE(VisitExpressionAnnotation(expr->value())); | 182 RECURSE(VisitExpressionAnnotation(expr->value(), false)); |
175 SetType(var, computed_type_); | 183 SetType(var, computed_type_); |
176 type->InitParameter(i, computed_type_); | 184 type->InitParameter(i, computed_type_); |
177 good = true; | 185 good = true; |
178 } | 186 } |
179 if (!good) FAIL(fun, "missing parameter type annotations"); | 187 if (!good) FAIL(fun, "missing parameter type annotations"); |
180 | 188 |
181 SetResult(fun, type); | 189 SetResult(fun, type); |
182 } | 190 } |
183 | 191 |
184 | 192 |
185 void AsmTyper::VisitExpressionAnnotation(Expression* expr) { | 193 void AsmTyper::VisitExpressionAnnotation(Expression* expr, bool is_return) { |
186 // Normal +x or x|0 annotations. | 194 // Normal +x or x|0 annotations. |
187 BinaryOperation* bin = expr->AsBinaryOperation(); | 195 BinaryOperation* bin = expr->AsBinaryOperation(); |
188 if (bin != NULL) { | 196 if (bin != NULL) { |
189 Literal* right = bin->right()->AsLiteral(); | 197 Literal* right = bin->right()->AsLiteral(); |
190 if (right != NULL) { | 198 if (right != NULL) { |
191 switch (bin->op()) { | 199 switch (bin->op()) { |
192 case Token::MUL: // We encode +x as 1*x | 200 case Token::MUL: // We encode +x as x*1.0 |
193 if (right->raw_value()->ContainsDot() && | 201 if (right->raw_value()->ContainsDot() && |
194 right->raw_value()->AsNumber() == 1.0) { | 202 right->raw_value()->AsNumber() == 1.0) { |
195 SetResult(expr, cache_.kFloat64); | 203 SetResult(expr, cache_.kAsmDouble); |
196 return; | 204 return; |
197 } | 205 } |
198 break; | 206 break; |
199 case Token::BIT_OR: | 207 case Token::BIT_OR: |
200 if (!right->raw_value()->ContainsDot() && | 208 if (!right->raw_value()->ContainsDot() && |
201 right->raw_value()->AsNumber() == 0.0) { | 209 right->raw_value()->AsNumber() == 0.0) { |
202 SetResult(expr, cache_.kInt32); | 210 if (is_return) { |
| 211 SetResult(expr, cache_.kAsmSigned); |
| 212 } else { |
| 213 SetResult(expr, cache_.kAsmInt); |
| 214 } |
203 return; | 215 return; |
204 } | 216 } |
205 break; | 217 break; |
206 default: | 218 default: |
207 break; | 219 break; |
208 } | 220 } |
209 } | 221 } |
210 FAIL(expr, "invalid type annotation on binary op"); | 222 FAIL(expr, "invalid type annotation on binary op"); |
211 } | 223 } |
212 | 224 |
213 // Numbers or the undefined literal (for empty returns). | 225 // Numbers or the undefined literal (for empty returns). |
214 if (expr->IsLiteral()) { | 226 if (expr->IsLiteral()) { |
215 RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal")); | 227 RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal")); |
216 return; | 228 return; |
217 } | 229 } |
218 | 230 |
219 Call* call = expr->AsCall(); | 231 Call* call = expr->AsCall(); |
220 if (call != NULL) { | 232 if (call != NULL) { |
221 if (call->expression()->IsVariableProxy()) { | 233 if (call->expression()->IsVariableProxy()) { |
222 RECURSE(VisitWithExpectation( | 234 RECURSE(VisitWithExpectation( |
223 call->expression(), Type::Any(zone()), | 235 call->expression(), Type::Any(zone()), |
224 "only fround allowed on expression annotations")); | 236 "only fround allowed on expression annotations")); |
225 if (!computed_type_->Is( | 237 if (!computed_type_->Is( |
226 Type::Function(cache_.kFloat32, Type::Number(zone()), zone()))) { | 238 Type::Function(cache_.kAsmFloat, Type::Number(zone()), zone()))) { |
227 FAIL(call->expression(), | 239 FAIL(call->expression(), |
228 "only fround allowed on expression annotations"); | 240 "only fround allowed on expression annotations"); |
229 } | 241 } |
230 if (call->arguments()->length() != 1) { | 242 if (call->arguments()->length() != 1) { |
231 FAIL(call, "invalid argument count calling fround"); | 243 FAIL(call, "invalid argument count calling fround"); |
232 } | 244 } |
233 SetResult(expr, cache_.kFloat32); | 245 SetResult(expr, cache_.kAsmFloat); |
234 return; | 246 return; |
235 } | 247 } |
236 } | 248 } |
237 | 249 |
238 FAIL(expr, "invalid type annotation"); | 250 FAIL(expr, "invalid type annotation"); |
239 } | 251 } |
240 | 252 |
241 | 253 |
242 void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) { | 254 void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) { |
243 for (int i = 0; i < stmts->length(); ++i) { | 255 for (int i = 0; i < stmts->length(); ++i) { |
(...skipping 23 matching lines...) Expand all Loading... |
267 } | 279 } |
268 | 280 |
269 | 281 |
270 void AsmTyper::VisitEmptyParentheses(EmptyParentheses* expr) { UNREACHABLE(); } | 282 void AsmTyper::VisitEmptyParentheses(EmptyParentheses* expr) { UNREACHABLE(); } |
271 | 283 |
272 | 284 |
273 void AsmTyper::VisitIfStatement(IfStatement* stmt) { | 285 void AsmTyper::VisitIfStatement(IfStatement* stmt) { |
274 if (!in_function_) { | 286 if (!in_function_) { |
275 FAIL(stmt, "if statement inside module body"); | 287 FAIL(stmt, "if statement inside module body"); |
276 } | 288 } |
277 RECURSE(VisitWithExpectation(stmt->condition(), cache_.kInt32, | 289 RECURSE(VisitWithExpectation(stmt->condition(), cache_.kAsmSigned, |
278 "if condition expected to be integer")); | 290 "if condition expected to be integer")); |
279 RECURSE(Visit(stmt->then_statement())); | 291 RECURSE(Visit(stmt->then_statement())); |
280 RECURSE(Visit(stmt->else_statement())); | 292 RECURSE(Visit(stmt->else_statement())); |
281 } | 293 } |
282 | 294 |
283 | 295 |
284 void AsmTyper::VisitContinueStatement(ContinueStatement* stmt) { | 296 void AsmTyper::VisitContinueStatement(ContinueStatement* stmt) { |
285 if (!in_function_) { | 297 if (!in_function_) { |
286 FAIL(stmt, "continue statement inside module body"); | 298 FAIL(stmt, "continue statement inside module body"); |
287 } | 299 } |
288 } | 300 } |
289 | 301 |
290 | 302 |
291 void AsmTyper::VisitBreakStatement(BreakStatement* stmt) { | 303 void AsmTyper::VisitBreakStatement(BreakStatement* stmt) { |
292 if (!in_function_) { | 304 if (!in_function_) { |
293 FAIL(stmt, "continue statement inside module body"); | 305 FAIL(stmt, "continue statement inside module body"); |
294 } | 306 } |
295 } | 307 } |
296 | 308 |
297 | 309 |
298 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) { | 310 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) { |
299 // Handle module return statement in VisitAsmModule. | 311 // Handle module return statement in VisitAsmModule. |
300 if (!in_function_) { | 312 if (!in_function_) { |
301 return; | 313 return; |
302 } | 314 } |
| 315 // Returning literals handled in annotations. |
| 316 if (stmt->expression()->IsLiteral()) { |
| 317 return; |
| 318 } |
303 RECURSE( | 319 RECURSE( |
304 VisitWithExpectation(stmt->expression(), return_type_, | 320 VisitWithExpectation(stmt->expression(), return_type_, |
305 "return expression expected to have return type")); | 321 "return expression expected to have return type")); |
306 } | 322 } |
307 | 323 |
308 | 324 |
309 void AsmTyper::VisitWithStatement(WithStatement* stmt) { | 325 void AsmTyper::VisitWithStatement(WithStatement* stmt) { |
310 FAIL(stmt, "bad with statement"); | 326 FAIL(stmt, "bad with statement"); |
311 } | 327 } |
312 | 328 |
313 | 329 |
314 void AsmTyper::VisitSwitchStatement(SwitchStatement* stmt) { | 330 void AsmTyper::VisitSwitchStatement(SwitchStatement* stmt) { |
315 if (!in_function_) { | 331 if (!in_function_) { |
316 FAIL(stmt, "switch statement inside module body"); | 332 FAIL(stmt, "switch statement inside module body"); |
317 } | 333 } |
318 RECURSE(VisitWithExpectation(stmt->tag(), cache_.kInt32, | 334 RECURSE(VisitWithExpectation(stmt->tag(), cache_.kAsmSigned, |
319 "switch expression non-integer")); | 335 "switch expression non-integer")); |
320 ZoneList<CaseClause*>* clauses = stmt->cases(); | 336 ZoneList<CaseClause*>* clauses = stmt->cases(); |
321 for (int i = 0; i < clauses->length(); ++i) { | 337 for (int i = 0; i < clauses->length(); ++i) { |
322 CaseClause* clause = clauses->at(i); | 338 CaseClause* clause = clauses->at(i); |
323 if (clause->is_default()) continue; | 339 if (clause->is_default()) continue; |
324 Expression* label = clause->label(); | 340 Expression* label = clause->label(); |
325 RECURSE( | 341 RECURSE(VisitWithExpectation(label, cache_.kAsmSigned, |
326 VisitWithExpectation(label, cache_.kInt32, "case label non-integer")); | 342 "case label non-integer")); |
327 if (!label->IsLiteral()) FAIL(label, "non-literal case label"); | 343 if (!label->IsLiteral()) FAIL(label, "non-literal case label"); |
328 Handle<Object> value = label->AsLiteral()->value(); | 344 Handle<Object> value = label->AsLiteral()->value(); |
329 int32_t value32; | 345 int32_t value32; |
330 if (!value->ToInt32(&value32)) FAIL(label, "illegal case label value"); | 346 if (!value->ToInt32(&value32)) FAIL(label, "illegal case label value"); |
331 // TODO(bradnelson): Detect duplicates. | 347 // TODO(bradnelson): Detect duplicates. |
332 ZoneList<Statement*>* stmts = clause->statements(); | 348 ZoneList<Statement*>* stmts = clause->statements(); |
333 RECURSE(VisitStatements(stmts)); | 349 RECURSE(VisitStatements(stmts)); |
334 } | 350 } |
335 } | 351 } |
336 | 352 |
337 | 353 |
338 void AsmTyper::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } | 354 void AsmTyper::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } |
339 | 355 |
340 | 356 |
341 void AsmTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { | 357 void AsmTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { |
342 if (!in_function_) { | 358 if (!in_function_) { |
343 FAIL(stmt, "do statement inside module body"); | 359 FAIL(stmt, "do statement inside module body"); |
344 } | 360 } |
345 RECURSE(Visit(stmt->body())); | 361 RECURSE(Visit(stmt->body())); |
346 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kInt32, | 362 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned, |
347 "do condition expected to be integer")); | 363 "do condition expected to be integer")); |
348 } | 364 } |
349 | 365 |
350 | 366 |
351 void AsmTyper::VisitWhileStatement(WhileStatement* stmt) { | 367 void AsmTyper::VisitWhileStatement(WhileStatement* stmt) { |
352 if (!in_function_) { | 368 if (!in_function_) { |
353 FAIL(stmt, "while statement inside module body"); | 369 FAIL(stmt, "while statement inside module body"); |
354 } | 370 } |
355 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kInt32, | 371 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned, |
356 "while condition expected to be integer")); | 372 "while condition expected to be integer")); |
357 RECURSE(Visit(stmt->body())); | 373 RECURSE(Visit(stmt->body())); |
358 } | 374 } |
359 | 375 |
360 | 376 |
361 void AsmTyper::VisitForStatement(ForStatement* stmt) { | 377 void AsmTyper::VisitForStatement(ForStatement* stmt) { |
362 if (!in_function_) { | 378 if (!in_function_) { |
363 FAIL(stmt, "for statement inside module body"); | 379 FAIL(stmt, "for statement inside module body"); |
364 } | 380 } |
365 if (stmt->init() != NULL) { | 381 if (stmt->init() != NULL) { |
366 RECURSE(Visit(stmt->init())); | 382 RECURSE(Visit(stmt->init())); |
367 } | 383 } |
368 if (stmt->cond() != NULL) { | 384 if (stmt->cond() != NULL) { |
369 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kInt32, | 385 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned, |
370 "for condition expected to be integer")); | 386 "for condition expected to be integer")); |
371 } | 387 } |
372 if (stmt->next() != NULL) { | 388 if (stmt->next() != NULL) { |
373 RECURSE(Visit(stmt->next())); | 389 RECURSE(Visit(stmt->next())); |
374 } | 390 } |
375 RECURSE(Visit(stmt->body())); | 391 RECURSE(Visit(stmt->body())); |
376 } | 392 } |
377 | 393 |
378 | 394 |
379 void AsmTyper::VisitForInStatement(ForInStatement* stmt) { | 395 void AsmTyper::VisitForInStatement(ForInStatement* stmt) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 FAIL(expr, "function info literal encountered"); | 445 FAIL(expr, "function info literal encountered"); |
430 } | 446 } |
431 | 447 |
432 | 448 |
433 void AsmTyper::VisitDoExpression(DoExpression* expr) { | 449 void AsmTyper::VisitDoExpression(DoExpression* expr) { |
434 FAIL(expr, "do-expression encountered"); | 450 FAIL(expr, "do-expression encountered"); |
435 } | 451 } |
436 | 452 |
437 | 453 |
438 void AsmTyper::VisitConditional(Conditional* expr) { | 454 void AsmTyper::VisitConditional(Conditional* expr) { |
439 RECURSE(VisitWithExpectation(expr->condition(), cache_.kInt32, | 455 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(), |
440 "condition expected to be integer")); | 456 "condition expected to be integer")); |
| 457 if (!computed_type_->Is(cache_.kAsmInt)) { |
| 458 FAIL(expr->condition(), "condition must be of type int"); |
| 459 } |
| 460 |
441 RECURSE(VisitWithExpectation( | 461 RECURSE(VisitWithExpectation( |
442 expr->then_expression(), expected_type_, | 462 expr->then_expression(), expected_type_, |
443 "conditional then branch type mismatch with enclosing expression")); | 463 "conditional then branch type mismatch with enclosing expression")); |
444 Type* then_type = computed_type_; | 464 Type* then_type = StorageType(computed_type_); |
| 465 if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) { |
| 466 FAIL(expr->then_expression(), "invalid type in ? then expression"); |
| 467 } |
| 468 |
445 RECURSE(VisitWithExpectation( | 469 RECURSE(VisitWithExpectation( |
446 expr->else_expression(), expected_type_, | 470 expr->else_expression(), expected_type_, |
447 "conditional else branch type mismatch with enclosing expression")); | 471 "conditional else branch type mismatch with enclosing expression")); |
448 Type* else_type = computed_type_; | 472 Type* else_type = StorageType(computed_type_); |
449 Type* type = Type::Union(then_type, else_type, zone()); | 473 if (intish_ != 0 || !else_type->Is(cache_.kAsmComparable)) { |
450 if (!(type->Is(cache_.kInt32) || type->Is(cache_.kUint32) || | 474 FAIL(expr->else_expression(), "invalid type in ? else expression"); |
451 type->Is(cache_.kFloat32) || type->Is(cache_.kFloat64))) { | |
452 FAIL(expr, "ill-typed conditional"); | |
453 } | 475 } |
454 IntersectResult(expr, type); | 476 |
| 477 if (!then_type->Is(else_type) || !else_type->Is(then_type)) { |
| 478 FAIL(expr, "then and else expressions in ? must have the same type"); |
| 479 } |
| 480 |
| 481 IntersectResult(expr, then_type); |
455 } | 482 } |
456 | 483 |
457 | 484 |
458 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { | 485 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { |
459 Variable* var = expr->var(); | 486 Variable* var = expr->var(); |
460 if (GetType(var) == NULL) { | 487 if (GetType(var) == NULL) { |
461 FAIL(expr, "unbound variable"); | 488 FAIL(expr, "unbound variable"); |
462 } | 489 } |
463 Type* type = Type::Intersect(GetType(var), expected_type_, zone()); | 490 Type* type = Type::Intersect(GetType(var), expected_type_, zone()); |
464 if (type->Is(cache_.kInt32)) { | 491 if (type->Is(cache_.kAsmInt)) { |
465 type = cache_.kInt32; | 492 type = cache_.kAsmInt; |
466 } | 493 } |
467 SetType(var, type); | 494 SetType(var, type); |
468 intish_ = 0; | 495 intish_ = 0; |
469 IntersectResult(expr, type); | 496 IntersectResult(expr, type); |
470 } | 497 } |
471 | 498 |
472 | 499 |
473 void AsmTyper::VisitLiteral(Literal* expr) { | 500 void AsmTyper::VisitLiteral(Literal* expr, bool is_return) { |
474 intish_ = 0; | 501 intish_ = 0; |
475 Handle<Object> value = expr->value(); | 502 Handle<Object> value = expr->value(); |
476 if (value->IsNumber()) { | 503 if (value->IsNumber()) { |
477 int32_t i; | 504 int32_t i; |
478 uint32_t u; | 505 uint32_t u; |
479 if (expr->raw_value()->ContainsDot()) { | 506 if (expr->raw_value()->ContainsDot()) { |
480 IntersectResult(expr, cache_.kFloat64); | 507 IntersectResult(expr, cache_.kAsmDouble); |
481 } else if (value->ToUint32(&u)) { | 508 } else if (!is_return && value->ToUint32(&u)) { |
482 IntersectResult(expr, cache_.kInt32); | 509 if (u <= 0x7fffffff) { |
| 510 IntersectResult(expr, cache_.kAsmFixnum); |
| 511 } else { |
| 512 IntersectResult(expr, cache_.kAsmUnsigned); |
| 513 } |
483 } else if (value->ToInt32(&i)) { | 514 } else if (value->ToInt32(&i)) { |
484 IntersectResult(expr, cache_.kInt32); | 515 IntersectResult(expr, cache_.kAsmSigned); |
485 } else { | 516 } else { |
486 FAIL(expr, "illegal number"); | 517 FAIL(expr, "illegal number"); |
487 } | 518 } |
488 } else if (value->IsString()) { | 519 } else if (!is_return && value->IsString()) { |
489 IntersectResult(expr, Type::String()); | 520 IntersectResult(expr, Type::String()); |
490 } else if (value->IsUndefined()) { | 521 } else if (value->IsUndefined()) { |
491 IntersectResult(expr, Type::Undefined()); | 522 IntersectResult(expr, Type::Undefined()); |
492 } else { | 523 } else { |
493 FAIL(expr, "illegal literal"); | 524 FAIL(expr, "illegal literal"); |
494 } | 525 } |
495 } | 526 } |
496 | 527 |
497 | 528 |
| 529 void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); } |
| 530 |
| 531 |
498 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) { | 532 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) { |
499 FAIL(expr, "regular expression encountered"); | 533 FAIL(expr, "regular expression encountered"); |
500 } | 534 } |
501 | 535 |
502 | 536 |
503 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) { | 537 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) { |
504 if (in_function_) { | 538 if (in_function_) { |
505 FAIL(expr, "object literal in function"); | 539 FAIL(expr, "object literal in function"); |
506 } | 540 } |
507 // Allowed for asm module's export declaration. | 541 // Allowed for asm module's export declaration. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 } | 585 } |
552 } | 586 } |
553 } | 587 } |
554 if (expr->is_compound()) FAIL(expr, "compound assignment encountered"); | 588 if (expr->is_compound()) FAIL(expr, "compound assignment encountered"); |
555 Type* type = expected_type_; | 589 Type* type = expected_type_; |
556 RECURSE(VisitWithExpectation( | 590 RECURSE(VisitWithExpectation( |
557 expr->value(), type, "assignment value expected to match surrounding")); | 591 expr->value(), type, "assignment value expected to match surrounding")); |
558 if (intish_ != 0) { | 592 if (intish_ != 0) { |
559 FAIL(expr, "value still an intish"); | 593 FAIL(expr, "value still an intish"); |
560 } | 594 } |
561 RECURSE(VisitWithExpectation(expr->target(), computed_type_, | 595 Type* target_type = computed_type_; |
| 596 if (target_type->Is(cache_.kAsmInt)) { |
| 597 target_type = cache_.kAsmInt; |
| 598 } |
| 599 RECURSE(VisitWithExpectation(expr->target(), target_type, |
562 "assignment target expected to match value")); | 600 "assignment target expected to match value")); |
563 if (intish_ != 0) { | 601 if (intish_ != 0) { |
564 FAIL(expr, "value still an intish"); | 602 FAIL(expr, "value still an intish"); |
565 } | 603 } |
566 IntersectResult(expr, computed_type_); | 604 IntersectResult(expr, computed_type_); |
567 } | 605 } |
568 | 606 |
569 | 607 |
570 void AsmTyper::VisitYield(Yield* expr) { | 608 void AsmTyper::VisitYield(Yield* expr) { |
571 FAIL(expr, "yield expression encountered"); | 609 FAIL(expr, "yield expression encountered"); |
572 } | 610 } |
573 | 611 |
574 | 612 |
575 void AsmTyper::VisitThrow(Throw* expr) { | 613 void AsmTyper::VisitThrow(Throw* expr) { |
576 FAIL(expr, "throw statement encountered"); | 614 FAIL(expr, "throw statement encountered"); |
577 } | 615 } |
578 | 616 |
579 | 617 |
580 int AsmTyper::ElementShiftSize(Type* type) { | 618 int AsmTyper::ElementShiftSize(Type* type) { |
581 if (type->Is(cache_.kInt8) || type->Is(cache_.kUint8)) return 0; | 619 if (type->Is(cache_.kAsmSize8)) return 0; |
582 if (type->Is(cache_.kInt16) || type->Is(cache_.kUint16)) return 1; | 620 if (type->Is(cache_.kAsmSize16)) return 1; |
583 if (type->Is(cache_.kInt32) || type->Is(cache_.kUint32) || | 621 if (type->Is(cache_.kAsmSize32)) return 2; |
584 type->Is(cache_.kFloat32)) | 622 if (type->Is(cache_.kAsmSize64)) return 3; |
585 return 2; | |
586 if (type->Is(cache_.kFloat64)) return 3; | |
587 return -1; | 623 return -1; |
588 } | 624 } |
589 | 625 |
590 | 626 |
| 627 Type* AsmTyper::StorageType(Type* type) { |
| 628 if (type->Is(cache_.kAsmInt)) { |
| 629 return cache_.kAsmInt; |
| 630 } else { |
| 631 return type; |
| 632 } |
| 633 } |
| 634 |
| 635 |
591 void AsmTyper::VisitHeapAccess(Property* expr) { | 636 void AsmTyper::VisitHeapAccess(Property* expr) { |
592 Type::ArrayType* array_type = computed_type_->AsArray(); | 637 Type::ArrayType* array_type = computed_type_->AsArray(); |
593 size_t size = array_size_; | 638 size_t size = array_size_; |
594 Type* type = array_type->AsArray()->Element(); | 639 Type* type = array_type->AsArray()->Element(); |
595 if (type->IsFunction()) { | 640 if (type->IsFunction()) { |
596 BinaryOperation* bin = expr->key()->AsBinaryOperation(); | 641 BinaryOperation* bin = expr->key()->AsBinaryOperation(); |
597 if (bin == NULL || bin->op() != Token::BIT_AND) { | 642 if (bin == NULL || bin->op() != Token::BIT_AND) { |
598 FAIL(expr->key(), "expected & in call"); | 643 FAIL(expr->key(), "expected & in call"); |
599 } | 644 } |
600 RECURSE(VisitWithExpectation(bin->left(), cache_.kInt32, | 645 RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, |
601 "array index expected to be integer")); | 646 "array index expected to be integer")); |
602 Literal* right = bin->right()->AsLiteral(); | 647 Literal* right = bin->right()->AsLiteral(); |
603 if (right == NULL || right->raw_value()->ContainsDot()) { | 648 if (right == NULL || right->raw_value()->ContainsDot()) { |
604 FAIL(right, "call mask must be integer"); | 649 FAIL(right, "call mask must be integer"); |
605 } | 650 } |
606 RECURSE(VisitWithExpectation(bin->right(), cache_.kInt32, | 651 RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, |
607 "call mask expected to be integer")); | 652 "call mask expected to be integer")); |
608 if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) { | 653 if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) { |
609 FAIL(right, "call mask must match function table"); | 654 FAIL(right, "call mask must match function table"); |
610 } | 655 } |
611 bin->set_bounds(Bounds(cache_.kInt32)); | 656 bin->set_bounds(Bounds(cache_.kAsmSigned)); |
612 } else { | 657 } else { |
613 Literal* literal = expr->key()->AsLiteral(); | 658 Literal* literal = expr->key()->AsLiteral(); |
614 if (literal) { | 659 if (literal) { |
615 RECURSE(VisitWithExpectation(literal, cache_.kInt32, | 660 RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned, |
616 "array index expected to be integer")); | 661 "array index expected to be integer")); |
617 } else { | 662 } else { |
618 BinaryOperation* bin = expr->key()->AsBinaryOperation(); | 663 BinaryOperation* bin = expr->key()->AsBinaryOperation(); |
619 if (bin == NULL || bin->op() != Token::SAR) { | 664 if (bin == NULL || bin->op() != Token::SAR) { |
620 FAIL(expr->key(), "expected >> in heap access"); | 665 FAIL(expr->key(), "expected >> in heap access"); |
621 } | 666 } |
622 RECURSE(VisitWithExpectation(bin->left(), cache_.kInt32, | 667 RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, |
623 "array index expected to be integer")); | 668 "array index expected to be integer")); |
624 Literal* right = bin->right()->AsLiteral(); | 669 Literal* right = bin->right()->AsLiteral(); |
625 if (right == NULL || right->raw_value()->ContainsDot()) { | 670 if (right == NULL || right->raw_value()->ContainsDot()) { |
626 FAIL(right, "heap access shift must be integer"); | 671 FAIL(right, "heap access shift must be integer"); |
627 } | 672 } |
628 RECURSE(VisitWithExpectation(bin->right(), cache_.kInt32, | 673 RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, |
629 "array shift expected to be integer")); | 674 "array shift expected to be integer")); |
630 int n = static_cast<int>(right->raw_value()->AsNumber()); | 675 int n = static_cast<int>(right->raw_value()->AsNumber()); |
631 int expected_shift = ElementShiftSize(type); | 676 int expected_shift = ElementShiftSize(type); |
632 if (expected_shift < 0 || n != expected_shift) { | 677 if (expected_shift < 0 || n != expected_shift) { |
633 FAIL(right, "heap access shift must match element size"); | 678 FAIL(right, "heap access shift must match element size"); |
634 } | 679 } |
635 bin->set_bounds(Bounds(cache_.kInt32)); | 680 bin->set_bounds(Bounds(cache_.kAsmSigned)); |
636 } | 681 } |
637 } | 682 } |
638 IntersectResult(expr, type); | 683 IntersectResult(expr, type); |
639 } | 684 } |
640 | 685 |
641 | 686 |
642 void AsmTyper::VisitProperty(Property* expr) { | 687 void AsmTyper::VisitProperty(Property* expr) { |
643 // stdlib.Math.x | 688 // stdlib.Math.x |
644 Property* inner_prop = expr->obj()->AsProperty(); | 689 Property* inner_prop = expr->obj()->AsProperty(); |
645 if (inner_prop != NULL) { | 690 if (inner_prop != NULL) { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 | 818 |
774 | 819 |
775 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { | 820 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { |
776 // Allow runtime calls for now. | 821 // Allow runtime calls for now. |
777 } | 822 } |
778 | 823 |
779 | 824 |
780 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { | 825 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { |
781 switch (expr->op()) { | 826 switch (expr->op()) { |
782 case Token::NOT: // Used to encode != and !== | 827 case Token::NOT: // Used to encode != and !== |
783 RECURSE(VisitWithExpectation(expr->expression(), cache_.kInt32, | 828 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, |
784 "operand expected to be integer")); | 829 "operand expected to be integer")); |
785 IntersectResult(expr, cache_.kInt32); | 830 IntersectResult(expr, cache_.kAsmSigned); |
786 return; | 831 return; |
787 case Token::DELETE: | 832 case Token::DELETE: |
788 FAIL(expr, "delete operator encountered"); | 833 FAIL(expr, "delete operator encountered"); |
789 case Token::VOID: | 834 case Token::VOID: |
790 FAIL(expr, "void operator encountered"); | 835 FAIL(expr, "void operator encountered"); |
791 case Token::TYPEOF: | 836 case Token::TYPEOF: |
792 FAIL(expr, "typeof operator encountered"); | 837 FAIL(expr, "typeof operator encountered"); |
793 default: | 838 default: |
794 UNREACHABLE(); | 839 UNREACHABLE(); |
795 } | 840 } |
796 } | 841 } |
797 | 842 |
798 | 843 |
799 void AsmTyper::VisitCountOperation(CountOperation* expr) { | 844 void AsmTyper::VisitCountOperation(CountOperation* expr) { |
800 FAIL(expr, "increment or decrement operator encountered"); | 845 FAIL(expr, "increment or decrement operator encountered"); |
801 } | 846 } |
802 | 847 |
803 | 848 |
804 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, | 849 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, |
805 Type* left_expected, | 850 Type* left_expected, |
806 Type* right_expected, | 851 Type* right_expected, |
807 Type* result_type, bool conversion) { | 852 Type* result_type, bool conversion) { |
808 RECURSE(VisitWithExpectation(expr->left(), left_expected, | 853 RECURSE(VisitWithExpectation(expr->left(), Type::Number(), |
809 "left bit operand expected to be integer")); | 854 "left bitwise operand expected to be a number")); |
810 int left_intish = intish_; | 855 int left_intish = intish_; |
811 Type* left_type = computed_type_; | 856 Type* left_type = computed_type_; |
812 RECURSE(VisitWithExpectation(expr->right(), right_expected, | 857 if (!left_type->Is(left_expected)) { |
813 "right bit operand expected to be integer")); | 858 FAIL(expr->left(), "left bitwise operand expected to be an integer"); |
| 859 } |
| 860 if (left_intish > kMaxUncombinedAdditiveSteps) { |
| 861 FAIL(expr->left(), "too many consecutive additive ops"); |
| 862 } |
| 863 |
| 864 RECURSE( |
| 865 VisitWithExpectation(expr->right(), Type::Number(), |
| 866 "right bitwise operand expected to be a number")); |
814 int right_intish = intish_; | 867 int right_intish = intish_; |
815 Type* right_type = computed_type_; | 868 Type* right_type = computed_type_; |
816 if (left_intish > kMaxUncombinedAdditiveSteps) { | 869 if (!right_type->Is(right_expected)) { |
817 FAIL(expr, "too many consecutive additive ops"); | 870 FAIL(expr->right(), "right bitwise operand expected to be an integer"); |
818 } | 871 } |
819 if (right_intish > kMaxUncombinedAdditiveSteps) { | 872 if (right_intish > kMaxUncombinedAdditiveSteps) { |
820 FAIL(expr, "too many consecutive additive ops"); | 873 FAIL(expr->right(), "too many consecutive additive ops"); |
821 } | 874 } |
| 875 |
822 intish_ = 0; | 876 intish_ = 0; |
| 877 |
| 878 if (left_type->Is(cache_.kAsmFixnum) && right_type->Is(cache_.kAsmInt)) { |
| 879 left_type = right_type; |
| 880 } |
| 881 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) { |
| 882 right_type = left_type; |
| 883 } |
823 if (!conversion) { | 884 if (!conversion) { |
824 if (!left_type->Is(right_type) || !right_type->Is(left_type)) { | 885 if (!left_type->Is(right_type) || !right_type->Is(left_type)) { |
825 FAIL(expr, "ill typed bitwise operation"); | 886 FAIL(expr, "ill-typed bitwise operation"); |
826 } | 887 } |
827 } | 888 } |
828 IntersectResult(expr, result_type); | 889 IntersectResult(expr, result_type); |
829 } | 890 } |
830 | 891 |
831 | 892 |
832 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { | 893 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
833 switch (expr->op()) { | 894 switch (expr->op()) { |
834 case Token::COMMA: { | 895 case Token::COMMA: { |
835 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), | 896 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), |
836 "left comma operand expected to be any")); | 897 "left comma operand expected to be any")); |
837 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), | 898 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), |
838 "right comma operand expected to be any")); | 899 "right comma operand expected to be any")); |
839 IntersectResult(expr, computed_type_); | 900 IntersectResult(expr, computed_type_); |
840 return; | 901 return; |
841 } | 902 } |
842 case Token::OR: | 903 case Token::OR: |
843 case Token::AND: | 904 case Token::AND: |
844 FAIL(expr, "illegal logical operator"); | 905 FAIL(expr, "illegal logical operator"); |
845 case Token::BIT_OR: { | 906 case Token::BIT_OR: { |
846 // BIT_OR allows Any since it is used as a type coercion. | 907 // BIT_OR allows Any since it is used as a type coercion. |
847 VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kIntegral32, | 908 VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt, |
848 cache_.kInt32, true); | 909 cache_.kAsmSigned, true); |
849 return; | 910 return; |
850 } | 911 } |
851 case Token::BIT_XOR: { | 912 case Token::BIT_XOR: { |
852 // Handle booleans specially to handle de-sugared ! | 913 // Handle booleans specially to handle de-sugared ! |
853 Literal* left = expr->left()->AsLiteral(); | 914 Literal* left = expr->left()->AsLiteral(); |
854 if (left && left->value()->IsBoolean()) { | 915 if (left && left->value()->IsBoolean()) { |
855 if (left->ToBooleanIsTrue()) { | 916 if (left->ToBooleanIsTrue()) { |
856 left->set_bounds(Bounds(cache_.kSingletonOne)); | 917 left->set_bounds(Bounds(cache_.kSingletonOne)); |
857 RECURSE(VisitWithExpectation(expr->right(), cache_.kIntegral32, | 918 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt, |
858 "not operator expects an integer")); | 919 "not operator expects an integer")); |
859 IntersectResult(expr, cache_.kInt32); | 920 IntersectResult(expr, cache_.kAsmSigned); |
860 return; | 921 return; |
861 } else { | 922 } else { |
862 FAIL(left, "unexpected false"); | 923 FAIL(left, "unexpected false"); |
863 } | 924 } |
864 } | 925 } |
865 // BIT_XOR allows Number since it is used as a type coercion (via ~~). | 926 // BIT_XOR allows Number since it is used as a type coercion (via ~~). |
866 VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kIntegral32, | 927 VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kAsmInt, |
867 cache_.kInt32, true); | 928 cache_.kAsmSigned, true); |
868 return; | 929 return; |
869 } | 930 } |
870 case Token::SHR: { | 931 case Token::SHR: { |
871 VisitIntegerBitwiseOperator(expr, cache_.kIntegral32, cache_.kIntegral32, | 932 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, |
872 cache_.kUint32, false); | 933 cache_.kAsmUnsigned, false); |
873 return; | 934 return; |
874 } | 935 } |
875 case Token::SHL: | 936 case Token::SHL: |
876 case Token::SAR: | 937 case Token::SAR: |
877 case Token::BIT_AND: { | 938 case Token::BIT_AND: { |
878 VisitIntegerBitwiseOperator(expr, cache_.kIntegral32, cache_.kIntegral32, | 939 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, |
879 cache_.kInt32, false); | 940 cache_.kAsmSigned, false); |
880 return; | 941 return; |
881 } | 942 } |
882 case Token::ADD: | 943 case Token::ADD: |
883 case Token::SUB: | 944 case Token::SUB: |
884 case Token::MUL: | 945 case Token::MUL: |
885 case Token::DIV: | 946 case Token::DIV: |
886 case Token::MOD: { | 947 case Token::MOD: { |
887 RECURSE(VisitWithExpectation( | 948 RECURSE(VisitWithExpectation( |
888 expr->left(), Type::Number(), | 949 expr->left(), Type::Number(), |
889 "left arithmetic operand expected to be number")); | 950 "left arithmetic operand expected to be number")); |
890 Type* left_type = computed_type_; | 951 Type* left_type = computed_type_; |
891 int left_intish = intish_; | 952 int left_intish = intish_; |
892 RECURSE(VisitWithExpectation( | 953 RECURSE(VisitWithExpectation( |
893 expr->right(), Type::Number(), | 954 expr->right(), Type::Number(), |
894 "right arithmetic operand expected to be number")); | 955 "right arithmetic operand expected to be number")); |
895 Type* right_type = computed_type_; | 956 Type* right_type = computed_type_; |
896 int right_intish = intish_; | 957 int right_intish = intish_; |
897 Type* type = Type::Union(left_type, right_type, zone()); | 958 Type* type = Type::Union(left_type, right_type, zone()); |
898 if (type->Is(cache_.kInt32) || type->Is(cache_.kUint32)) { | 959 if (type->Is(cache_.kAsmInt)) { |
899 if (expr->op() == Token::MUL) { | 960 if (expr->op() == Token::MUL) { |
900 if (!expr->left()->IsLiteral() && !expr->right()->IsLiteral()) { | 961 Literal* right = expr->right()->AsLiteral(); |
| 962 if (!right) { |
901 FAIL(expr, "direct integer multiply forbidden"); | 963 FAIL(expr, "direct integer multiply forbidden"); |
902 } | 964 } |
903 intish_ = 0; | 965 if (!right->value()->IsNumber()) { |
904 IntersectResult(expr, cache_.kInt32); | 966 FAIL(expr, "multiply must be by an integer"); |
| 967 } |
| 968 int32_t i; |
| 969 if (!right->value()->ToInt32(&i)) { |
| 970 FAIL(expr, "multiply must be a signed integer"); |
| 971 } |
| 972 i = abs(i); |
| 973 if (i >= 1 << 20) { |
| 974 FAIL(expr, "multiply must be by value in -2^20 < n < 2^20"); |
| 975 } |
| 976 intish_ = i; |
| 977 IntersectResult(expr, cache_.kAsmInt); |
905 return; | 978 return; |
906 } else { | 979 } else { |
907 intish_ = left_intish + right_intish + 1; | 980 intish_ = left_intish + right_intish + 1; |
908 if (expr->op() == Token::ADD || expr->op() == Token::SUB) { | 981 if (expr->op() == Token::ADD || expr->op() == Token::SUB) { |
909 if (intish_ > kMaxUncombinedAdditiveSteps) { | 982 if (intish_ > kMaxUncombinedAdditiveSteps) { |
910 FAIL(expr, "too many consecutive additive ops"); | 983 FAIL(expr, "too many consecutive additive ops"); |
911 } | 984 } |
912 } else { | 985 } else { |
913 if (intish_ > kMaxUncombinedMultiplicativeSteps) { | 986 if (intish_ > kMaxUncombinedMultiplicativeSteps) { |
914 FAIL(expr, "too many consecutive multiplicative ops"); | 987 FAIL(expr, "too many consecutive multiplicative ops"); |
915 } | 988 } |
916 } | 989 } |
917 IntersectResult(expr, cache_.kInt32); | 990 IntersectResult(expr, cache_.kAsmInt); |
918 return; | 991 return; |
919 } | 992 } |
920 } else if (expr->op() == Token::MUL && | 993 } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmInt) && |
921 left_type->Is(cache_.kIntegral32) && | 994 right_type->Is(cache_.kAsmDouble)) { |
922 right_type->Is(cache_.kFloat64)) { | |
923 // For unary +, expressed as x * 1.0 | 995 // For unary +, expressed as x * 1.0 |
924 IntersectResult(expr, cache_.kFloat64); | 996 IntersectResult(expr, cache_.kAsmDouble); |
925 return; | 997 return; |
926 } else if (type->Is(cache_.kFloat32) && expr->op() != Token::MOD) { | 998 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { |
927 IntersectResult(expr, cache_.kFloat32); | 999 IntersectResult(expr, cache_.kAsmFloat); |
928 return; | 1000 return; |
929 } else if (type->Is(cache_.kFloat64)) { | 1001 } else if (type->Is(cache_.kAsmDouble)) { |
930 IntersectResult(expr, cache_.kFloat64); | 1002 IntersectResult(expr, cache_.kAsmDouble); |
931 return; | 1003 return; |
932 } else { | 1004 } else { |
933 FAIL(expr, "ill-typed arithmetic operation"); | 1005 FAIL(expr, "ill-typed arithmetic operation"); |
934 } | 1006 } |
935 } | 1007 } |
936 default: | 1008 default: |
937 UNREACHABLE(); | 1009 UNREACHABLE(); |
938 } | 1010 } |
939 } | 1011 } |
940 | 1012 |
941 | 1013 |
942 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { | 1014 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { |
943 RECURSE( | |
944 VisitWithExpectation(expr->left(), Type::Number(), | |
945 "left comparison operand expected to be number")); | |
946 Type* left_type = computed_type_; | |
947 RECURSE( | |
948 VisitWithExpectation(expr->right(), Type::Number(), | |
949 "right comparison operand expected to be number")); | |
950 Token::Value op = expr->op(); | 1015 Token::Value op = expr->op(); |
951 if (op != Token::EQ && op != Token::NE && op != Token::LT && | 1016 if (op != Token::EQ && op != Token::NE && op != Token::LT && |
952 op != Token::LTE && op != Token::GT && op != Token::GTE) { | 1017 op != Token::LTE && op != Token::GT && op != Token::GTE) { |
953 FAIL(expr, "illegal comparison operator"); | 1018 FAIL(expr, "illegal comparison operator"); |
954 } | 1019 } |
| 1020 |
| 1021 RECURSE( |
| 1022 VisitWithExpectation(expr->left(), Type::Number(), |
| 1023 "left comparison operand expected to be number")); |
| 1024 Type* left_type = computed_type_; |
| 1025 if (!left_type->Is(cache_.kAsmComparable)) { |
| 1026 FAIL(expr->left(), "bad type on left side of comparison"); |
| 1027 } |
| 1028 |
| 1029 RECURSE( |
| 1030 VisitWithExpectation(expr->right(), Type::Number(), |
| 1031 "right comparison operand expected to be number")); |
955 Type* right_type = computed_type_; | 1032 Type* right_type = computed_type_; |
956 Type* type = Type::Union(left_type, right_type, zone()); | 1033 if (!right_type->Is(cache_.kAsmComparable)) { |
957 expr->set_combined_type(type); | 1034 FAIL(expr->right(), "bad type on right side of comparison"); |
958 if (type->Is(cache_.kInt32) || type->Is(cache_.kUint32) || | |
959 type->Is(cache_.kFloat32) || type->Is(cache_.kFloat64)) { | |
960 IntersectResult(expr, cache_.kInt32); | |
961 } else { | |
962 FAIL(expr, "ill-typed comparison operation"); | |
963 } | 1035 } |
| 1036 |
| 1037 if (!left_type->Is(right_type) && !right_type->Is(left_type)) { |
| 1038 FAIL(expr, "left and right side of comparison must match"); |
| 1039 } |
| 1040 |
| 1041 IntersectResult(expr, cache_.kAsmSigned); |
964 } | 1042 } |
965 | 1043 |
966 | 1044 |
967 void AsmTyper::VisitThisFunction(ThisFunction* expr) { | 1045 void AsmTyper::VisitThisFunction(ThisFunction* expr) { |
968 FAIL(expr, "this function not allowed"); | 1046 FAIL(expr, "this function not allowed"); |
969 } | 1047 } |
970 | 1048 |
971 | 1049 |
972 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { | 1050 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { |
973 for (int i = 0; i < decls->length(); ++i) { | 1051 for (int i = 0; i < decls->length(); ++i) { |
(...skipping 26 matching lines...) Expand all Loading... |
1000 } | 1078 } |
1001 | 1079 |
1002 | 1080 |
1003 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { | 1081 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { |
1004 FAIL(expr, "call reference not allowed"); | 1082 FAIL(expr, "call reference not allowed"); |
1005 } | 1083 } |
1006 | 1084 |
1007 | 1085 |
1008 void AsmTyper::InitializeStdlib() { | 1086 void AsmTyper::InitializeStdlib() { |
1009 Type* number_type = Type::Number(zone()); | 1087 Type* number_type = Type::Number(zone()); |
1010 Type* double_type = cache_.kFloat64; | 1088 Type* double_type = cache_.kAsmDouble; |
1011 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); | 1089 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); |
1012 Type* double_fn2_type = | 1090 Type* double_fn2_type = |
1013 Type::Function(double_type, double_type, double_type, zone()); | 1091 Type::Function(double_type, double_type, double_type, zone()); |
1014 | 1092 |
1015 Type* fround_type = Type::Function(cache_.kFloat32, number_type, zone()); | 1093 Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone()); |
1016 Type* imul_type = | 1094 Type* imul_type = |
1017 Type::Function(cache_.kInt32, cache_.kInt32, cache_.kInt32, zone()); | 1095 Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone()); |
1018 // TODO(bradnelson): currently only approximating the proper intersection type | 1096 // TODO(bradnelson): currently only approximating the proper intersection type |
1019 // (which we cannot currently represent). | 1097 // (which we cannot currently represent). |
1020 Type* abs_type = Type::Function(number_type, number_type, zone()); | 1098 Type* abs_type = Type::Function(number_type, number_type, zone()); |
1021 | 1099 |
1022 struct Assignment { | 1100 struct Assignment { |
1023 const char* name; | 1101 const char* name; |
1024 Type* type; | 1102 Type* type; |
1025 }; | 1103 }; |
1026 | 1104 |
1027 const Assignment math[] = { | 1105 const Assignment math[] = { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1124 computed_type_->Print(); | 1202 computed_type_->Print(); |
1125 PrintF("Expected type: "); | 1203 PrintF("Expected type: "); |
1126 expected_type_->Print(); | 1204 expected_type_->Print(); |
1127 #endif | 1205 #endif |
1128 FAIL(expr, msg); | 1206 FAIL(expr, msg); |
1129 } | 1207 } |
1130 expected_type_ = save; | 1208 expected_type_ = save; |
1131 } | 1209 } |
1132 } // namespace internal | 1210 } // namespace internal |
1133 } // namespace v8 | 1211 } // namespace v8 |
OLD | NEW |