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(), cache_.kAsmSigned, |
440 "condition expected to be integer")); | 456 "condition expected to be integer")); |
441 RECURSE(VisitWithExpectation( | 457 RECURSE(VisitWithExpectation( |
442 expr->then_expression(), expected_type_, | 458 expr->then_expression(), expected_type_, |
443 "conditional then branch type mismatch with enclosing expression")); | 459 "conditional then branch type mismatch with enclosing expression")); |
444 Type* then_type = computed_type_; | 460 Type* then_type = computed_type_; |
445 RECURSE(VisitWithExpectation( | 461 RECURSE(VisitWithExpectation( |
446 expr->else_expression(), expected_type_, | 462 expr->else_expression(), expected_type_, |
447 "conditional else branch type mismatch with enclosing expression")); | 463 "conditional else branch type mismatch with enclosing expression")); |
448 Type* else_type = computed_type_; | 464 Type* else_type = computed_type_; |
449 Type* type = Type::Union(then_type, else_type, zone()); | 465 Type* type = Type::Union(then_type, else_type, zone()); |
450 if (!(type->Is(cache_.kInt32) || type->Is(cache_.kUint32) || | 466 if (!(type->Is(cache_.kAsmSigned) || type->Is(cache_.kAsmUnsigned) || |
titzer
2015/11/17 09:25:21
Maybe we need to have a type that represents the u
bradn
2015/11/17 19:25:01
Revised to leverage pre-cooked unions more.
| |
451 type->Is(cache_.kFloat32) || type->Is(cache_.kFloat64))) { | 467 type->Is(cache_.kAsmFloat) || type->Is(cache_.kAsmDouble))) { |
452 FAIL(expr, "ill-typed conditional"); | 468 FAIL(expr, "ill-typed conditional"); |
453 } | 469 } |
454 IntersectResult(expr, type); | 470 IntersectResult(expr, type); |
455 } | 471 } |
456 | 472 |
457 | 473 |
458 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { | 474 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { |
459 Variable* var = expr->var(); | 475 Variable* var = expr->var(); |
460 if (GetType(var) == NULL) { | 476 if (GetType(var) == NULL) { |
461 FAIL(expr, "unbound variable"); | 477 FAIL(expr, "unbound variable"); |
462 } | 478 } |
463 Type* type = Type::Intersect(GetType(var), expected_type_, zone()); | 479 Type* type = Type::Intersect(GetType(var), expected_type_, zone()); |
464 if (type->Is(cache_.kInt32)) { | 480 if (type->Is(cache_.kAsmInt)) { |
465 type = cache_.kInt32; | 481 type = cache_.kAsmInt; |
466 } | 482 } |
467 SetType(var, type); | 483 SetType(var, type); |
468 intish_ = 0; | 484 intish_ = 0; |
469 IntersectResult(expr, type); | 485 IntersectResult(expr, type); |
470 } | 486 } |
471 | 487 |
472 | 488 |
473 void AsmTyper::VisitLiteral(Literal* expr) { | 489 void AsmTyper::VisitLiteral(Literal* expr, bool is_return) { |
474 intish_ = 0; | 490 intish_ = 0; |
475 Handle<Object> value = expr->value(); | 491 Handle<Object> value = expr->value(); |
476 if (value->IsNumber()) { | 492 if (value->IsNumber()) { |
477 int32_t i; | 493 int32_t i; |
478 uint32_t u; | 494 uint32_t u; |
479 if (expr->raw_value()->ContainsDot()) { | 495 if (expr->raw_value()->ContainsDot()) { |
480 IntersectResult(expr, cache_.kFloat64); | 496 IntersectResult(expr, cache_.kAsmDouble); |
481 } else if (value->ToUint32(&u)) { | 497 } else if (!is_return && value->ToUint32(&u)) { |
482 IntersectResult(expr, cache_.kInt32); | 498 if (u <= 0x7fffffff) { |
499 IntersectResult(expr, cache_.kAsmFixnum); | |
500 } else { | |
501 IntersectResult(expr, cache_.kAsmUnsigned); | |
502 } | |
483 } else if (value->ToInt32(&i)) { | 503 } else if (value->ToInt32(&i)) { |
484 IntersectResult(expr, cache_.kInt32); | 504 IntersectResult(expr, cache_.kAsmSigned); |
485 } else { | 505 } else { |
486 FAIL(expr, "illegal number"); | 506 FAIL(expr, "illegal number"); |
487 } | 507 } |
488 } else if (value->IsString()) { | 508 } else if (!is_return && value->IsString()) { |
489 IntersectResult(expr, Type::String()); | 509 IntersectResult(expr, Type::String()); |
490 } else if (value->IsUndefined()) { | 510 } else if (value->IsUndefined()) { |
491 IntersectResult(expr, Type::Undefined()); | 511 IntersectResult(expr, Type::Undefined()); |
492 } else { | 512 } else { |
493 FAIL(expr, "illegal literal"); | 513 FAIL(expr, "illegal literal"); |
494 } | 514 } |
495 } | 515 } |
496 | 516 |
497 | 517 |
518 void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); } | |
519 | |
520 | |
498 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) { | 521 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) { |
499 FAIL(expr, "regular expression encountered"); | 522 FAIL(expr, "regular expression encountered"); |
500 } | 523 } |
501 | 524 |
502 | 525 |
503 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) { | 526 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) { |
504 if (in_function_) { | 527 if (in_function_) { |
505 FAIL(expr, "object literal in function"); | 528 FAIL(expr, "object literal in function"); |
506 } | 529 } |
507 // Allowed for asm module's export declaration. | 530 // Allowed for asm module's export declaration. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
551 } | 574 } |
552 } | 575 } |
553 } | 576 } |
554 if (expr->is_compound()) FAIL(expr, "compound assignment encountered"); | 577 if (expr->is_compound()) FAIL(expr, "compound assignment encountered"); |
555 Type* type = expected_type_; | 578 Type* type = expected_type_; |
556 RECURSE(VisitWithExpectation( | 579 RECURSE(VisitWithExpectation( |
557 expr->value(), type, "assignment value expected to match surrounding")); | 580 expr->value(), type, "assignment value expected to match surrounding")); |
558 if (intish_ != 0) { | 581 if (intish_ != 0) { |
559 FAIL(expr, "value still an intish"); | 582 FAIL(expr, "value still an intish"); |
560 } | 583 } |
561 RECURSE(VisitWithExpectation(expr->target(), computed_type_, | 584 Type* target_type = computed_type_; |
585 if (target_type->Is(cache_.kAsmInt)) { | |
586 target_type = cache_.kAsmInt; | |
587 } | |
588 RECURSE(VisitWithExpectation(expr->target(), target_type, | |
562 "assignment target expected to match value")); | 589 "assignment target expected to match value")); |
563 if (intish_ != 0) { | 590 if (intish_ != 0) { |
564 FAIL(expr, "value still an intish"); | 591 FAIL(expr, "value still an intish"); |
565 } | 592 } |
566 IntersectResult(expr, computed_type_); | 593 IntersectResult(expr, computed_type_); |
567 } | 594 } |
568 | 595 |
569 | 596 |
570 void AsmTyper::VisitYield(Yield* expr) { | 597 void AsmTyper::VisitYield(Yield* expr) { |
571 FAIL(expr, "yield expression encountered"); | 598 FAIL(expr, "yield expression encountered"); |
572 } | 599 } |
573 | 600 |
574 | 601 |
575 void AsmTyper::VisitThrow(Throw* expr) { | 602 void AsmTyper::VisitThrow(Throw* expr) { |
576 FAIL(expr, "throw statement encountered"); | 603 FAIL(expr, "throw statement encountered"); |
577 } | 604 } |
578 | 605 |
579 | 606 |
580 int AsmTyper::ElementShiftSize(Type* type) { | 607 int AsmTyper::ElementShiftSize(Type* type) { |
581 if (type->Is(cache_.kInt8) || type->Is(cache_.kUint8)) return 0; | 608 if (type->Is(cache_.kInt8) || type->Is(cache_.kUint8)) return 0; |
582 if (type->Is(cache_.kInt16) || type->Is(cache_.kUint16)) return 1; | 609 if (type->Is(cache_.kInt16) || type->Is(cache_.kUint16)) return 1; |
583 if (type->Is(cache_.kInt32) || type->Is(cache_.kUint32) || | 610 if (type->Is(cache_.kAsmSigned) || type->Is(cache_.kAsmUnsigned) || |
584 type->Is(cache_.kFloat32)) | 611 type->Is(cache_.kAsmFloat)) |
585 return 2; | 612 return 2; |
586 if (type->Is(cache_.kFloat64)) return 3; | 613 if (type->Is(cache_.kAsmDouble)) return 3; |
587 return -1; | 614 return -1; |
588 } | 615 } |
589 | 616 |
590 | 617 |
591 void AsmTyper::VisitHeapAccess(Property* expr) { | 618 void AsmTyper::VisitHeapAccess(Property* expr) { |
592 Type::ArrayType* array_type = computed_type_->AsArray(); | 619 Type::ArrayType* array_type = computed_type_->AsArray(); |
593 size_t size = array_size_; | 620 size_t size = array_size_; |
594 Type* type = array_type->AsArray()->Element(); | 621 Type* type = array_type->AsArray()->Element(); |
595 if (type->IsFunction()) { | 622 if (type->IsFunction()) { |
596 BinaryOperation* bin = expr->key()->AsBinaryOperation(); | 623 BinaryOperation* bin = expr->key()->AsBinaryOperation(); |
597 if (bin == NULL || bin->op() != Token::BIT_AND) { | 624 if (bin == NULL || bin->op() != Token::BIT_AND) { |
598 FAIL(expr->key(), "expected & in call"); | 625 FAIL(expr->key(), "expected & in call"); |
599 } | 626 } |
600 RECURSE(VisitWithExpectation(bin->left(), cache_.kInt32, | 627 RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, |
601 "array index expected to be integer")); | 628 "array index expected to be integer")); |
602 Literal* right = bin->right()->AsLiteral(); | 629 Literal* right = bin->right()->AsLiteral(); |
603 if (right == NULL || right->raw_value()->ContainsDot()) { | 630 if (right == NULL || right->raw_value()->ContainsDot()) { |
604 FAIL(right, "call mask must be integer"); | 631 FAIL(right, "call mask must be integer"); |
605 } | 632 } |
606 RECURSE(VisitWithExpectation(bin->right(), cache_.kInt32, | 633 RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, |
607 "call mask expected to be integer")); | 634 "call mask expected to be integer")); |
608 if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) { | 635 if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) { |
609 FAIL(right, "call mask must match function table"); | 636 FAIL(right, "call mask must match function table"); |
610 } | 637 } |
611 bin->set_bounds(Bounds(cache_.kInt32)); | 638 bin->set_bounds(Bounds(cache_.kAsmSigned)); |
612 } else { | 639 } else { |
613 Literal* literal = expr->key()->AsLiteral(); | 640 Literal* literal = expr->key()->AsLiteral(); |
614 if (literal) { | 641 if (literal) { |
615 RECURSE(VisitWithExpectation(literal, cache_.kInt32, | 642 RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned, |
616 "array index expected to be integer")); | 643 "array index expected to be integer")); |
617 } else { | 644 } else { |
618 BinaryOperation* bin = expr->key()->AsBinaryOperation(); | 645 BinaryOperation* bin = expr->key()->AsBinaryOperation(); |
619 if (bin == NULL || bin->op() != Token::SAR) { | 646 if (bin == NULL || bin->op() != Token::SAR) { |
620 FAIL(expr->key(), "expected >> in heap access"); | 647 FAIL(expr->key(), "expected >> in heap access"); |
621 } | 648 } |
622 RECURSE(VisitWithExpectation(bin->left(), cache_.kInt32, | 649 RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, |
623 "array index expected to be integer")); | 650 "array index expected to be integer")); |
624 Literal* right = bin->right()->AsLiteral(); | 651 Literal* right = bin->right()->AsLiteral(); |
625 if (right == NULL || right->raw_value()->ContainsDot()) { | 652 if (right == NULL || right->raw_value()->ContainsDot()) { |
626 FAIL(right, "heap access shift must be integer"); | 653 FAIL(right, "heap access shift must be integer"); |
627 } | 654 } |
628 RECURSE(VisitWithExpectation(bin->right(), cache_.kInt32, | 655 RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, |
629 "array shift expected to be integer")); | 656 "array shift expected to be integer")); |
630 int n = static_cast<int>(right->raw_value()->AsNumber()); | 657 int n = static_cast<int>(right->raw_value()->AsNumber()); |
631 int expected_shift = ElementShiftSize(type); | 658 int expected_shift = ElementShiftSize(type); |
632 if (expected_shift < 0 || n != expected_shift) { | 659 if (expected_shift < 0 || n != expected_shift) { |
633 FAIL(right, "heap access shift must match element size"); | 660 FAIL(right, "heap access shift must match element size"); |
634 } | 661 } |
635 bin->set_bounds(Bounds(cache_.kInt32)); | 662 bin->set_bounds(Bounds(cache_.kAsmSigned)); |
636 } | 663 } |
637 } | 664 } |
638 IntersectResult(expr, type); | 665 IntersectResult(expr, type); |
639 } | 666 } |
640 | 667 |
641 | 668 |
642 void AsmTyper::VisitProperty(Property* expr) { | 669 void AsmTyper::VisitProperty(Property* expr) { |
643 // stdlib.Math.x | 670 // stdlib.Math.x |
644 Property* inner_prop = expr->obj()->AsProperty(); | 671 Property* inner_prop = expr->obj()->AsProperty(); |
645 if (inner_prop != NULL) { | 672 if (inner_prop != NULL) { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
773 | 800 |
774 | 801 |
775 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { | 802 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { |
776 // Allow runtime calls for now. | 803 // Allow runtime calls for now. |
777 } | 804 } |
778 | 805 |
779 | 806 |
780 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { | 807 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { |
781 switch (expr->op()) { | 808 switch (expr->op()) { |
782 case Token::NOT: // Used to encode != and !== | 809 case Token::NOT: // Used to encode != and !== |
783 RECURSE(VisitWithExpectation(expr->expression(), cache_.kInt32, | 810 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, |
784 "operand expected to be integer")); | 811 "operand expected to be integer")); |
785 IntersectResult(expr, cache_.kInt32); | 812 IntersectResult(expr, cache_.kAsmSigned); |
786 return; | 813 return; |
787 case Token::DELETE: | 814 case Token::DELETE: |
788 FAIL(expr, "delete operator encountered"); | 815 FAIL(expr, "delete operator encountered"); |
789 case Token::VOID: | 816 case Token::VOID: |
790 FAIL(expr, "void operator encountered"); | 817 FAIL(expr, "void operator encountered"); |
791 case Token::TYPEOF: | 818 case Token::TYPEOF: |
792 FAIL(expr, "typeof operator encountered"); | 819 FAIL(expr, "typeof operator encountered"); |
793 default: | 820 default: |
794 UNREACHABLE(); | 821 UNREACHABLE(); |
795 } | 822 } |
796 } | 823 } |
797 | 824 |
798 | 825 |
799 void AsmTyper::VisitCountOperation(CountOperation* expr) { | 826 void AsmTyper::VisitCountOperation(CountOperation* expr) { |
800 FAIL(expr, "increment or decrement operator encountered"); | 827 FAIL(expr, "increment or decrement operator encountered"); |
801 } | 828 } |
802 | 829 |
803 | 830 |
804 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, | 831 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, |
805 Type* left_expected, | 832 Type* left_expected, |
806 Type* right_expected, | 833 Type* right_expected, |
807 Type* result_type, bool conversion) { | 834 Type* result_type, bool conversion) { |
808 RECURSE(VisitWithExpectation(expr->left(), left_expected, | 835 RECURSE(VisitWithExpectation(expr->left(), Type::Number(), |
809 "left bit operand expected to be integer")); | 836 "left bitwise operand expected to be a number")); |
810 int left_intish = intish_; | 837 int left_intish = intish_; |
811 Type* left_type = computed_type_; | 838 Type* left_type = computed_type_; |
812 RECURSE(VisitWithExpectation(expr->right(), right_expected, | 839 if (!left_type->Is(left_expected)) { |
813 "right bit operand expected to be integer")); | 840 FAIL(expr->left(), "left bitwise operand expected to be an integer"); |
841 } | |
842 if (left_intish > kMaxUncombinedAdditiveSteps) { | |
843 FAIL(expr->left(), "too many consecutive additive ops"); | |
844 } | |
845 | |
846 RECURSE( | |
847 VisitWithExpectation(expr->right(), Type::Number(), | |
848 "right bitwise operand expected to be a number")); | |
814 int right_intish = intish_; | 849 int right_intish = intish_; |
815 Type* right_type = computed_type_; | 850 Type* right_type = computed_type_; |
816 if (left_intish > kMaxUncombinedAdditiveSteps) { | 851 if (!right_type->Is(right_expected)) { |
817 FAIL(expr, "too many consecutive additive ops"); | 852 FAIL(expr->right(), "right bitwise operand expected to be an integer"); |
818 } | 853 } |
819 if (right_intish > kMaxUncombinedAdditiveSteps) { | 854 if (right_intish > kMaxUncombinedAdditiveSteps) { |
820 FAIL(expr, "too many consecutive additive ops"); | 855 FAIL(expr->right(), "too many consecutive additive ops"); |
821 } | 856 } |
857 | |
822 intish_ = 0; | 858 intish_ = 0; |
859 | |
860 if (left_type->Is(cache_.kAsmFixnum) && right_type->Is(cache_.kAsmInt)) { | |
861 left_type = right_type; | |
862 } | |
863 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) { | |
864 right_type = left_type; | |
865 } | |
823 if (!conversion) { | 866 if (!conversion) { |
824 if (!left_type->Is(right_type) || !right_type->Is(left_type)) { | 867 if (!left_type->Is(right_type) || !right_type->Is(left_type)) { |
825 FAIL(expr, "ill typed bitwise operation"); | 868 FAIL(expr, "ill-typed bitwise operation"); |
826 } | 869 } |
827 } | 870 } |
828 IntersectResult(expr, result_type); | 871 IntersectResult(expr, result_type); |
829 } | 872 } |
830 | 873 |
831 | 874 |
832 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { | 875 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
833 switch (expr->op()) { | 876 switch (expr->op()) { |
834 case Token::COMMA: { | 877 case Token::COMMA: { |
835 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), | 878 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), |
836 "left comma operand expected to be any")); | 879 "left comma operand expected to be any")); |
837 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), | 880 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), |
838 "right comma operand expected to be any")); | 881 "right comma operand expected to be any")); |
839 IntersectResult(expr, computed_type_); | 882 IntersectResult(expr, computed_type_); |
840 return; | 883 return; |
841 } | 884 } |
842 case Token::OR: | 885 case Token::OR: |
843 case Token::AND: | 886 case Token::AND: |
844 FAIL(expr, "illegal logical operator"); | 887 FAIL(expr, "illegal logical operator"); |
845 case Token::BIT_OR: { | 888 case Token::BIT_OR: { |
846 // BIT_OR allows Any since it is used as a type coercion. | 889 // BIT_OR allows Any since it is used as a type coercion. |
847 VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kIntegral32, | 890 VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt, |
848 cache_.kInt32, true); | 891 cache_.kAsmSigned, true); |
849 return; | 892 return; |
850 } | 893 } |
851 case Token::BIT_XOR: { | 894 case Token::BIT_XOR: { |
852 // Handle booleans specially to handle de-sugared ! | 895 // Handle booleans specially to handle de-sugared ! |
853 Literal* left = expr->left()->AsLiteral(); | 896 Literal* left = expr->left()->AsLiteral(); |
854 if (left && left->value()->IsBoolean()) { | 897 if (left && left->value()->IsBoolean()) { |
855 if (left->ToBooleanIsTrue()) { | 898 if (left->ToBooleanIsTrue()) { |
856 left->set_bounds(Bounds(cache_.kSingletonOne)); | 899 left->set_bounds(Bounds(cache_.kSingletonOne)); |
857 RECURSE(VisitWithExpectation(expr->right(), cache_.kIntegral32, | 900 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt, |
858 "not operator expects an integer")); | 901 "not operator expects an integer")); |
859 IntersectResult(expr, cache_.kInt32); | 902 IntersectResult(expr, cache_.kAsmSigned); |
860 return; | 903 return; |
861 } else { | 904 } else { |
862 FAIL(left, "unexpected false"); | 905 FAIL(left, "unexpected false"); |
863 } | 906 } |
864 } | 907 } |
865 // BIT_XOR allows Number since it is used as a type coercion (via ~~). | 908 // BIT_XOR allows Number since it is used as a type coercion (via ~~). |
866 VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kIntegral32, | 909 VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kAsmInt, |
867 cache_.kInt32, true); | 910 cache_.kAsmSigned, true); |
868 return; | 911 return; |
869 } | 912 } |
870 case Token::SHR: { | 913 case Token::SHR: { |
871 VisitIntegerBitwiseOperator(expr, cache_.kIntegral32, cache_.kIntegral32, | 914 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, |
872 cache_.kUint32, false); | 915 cache_.kAsmUnsigned, false); |
873 return; | 916 return; |
874 } | 917 } |
875 case Token::SHL: | 918 case Token::SHL: |
876 case Token::SAR: | 919 case Token::SAR: |
877 case Token::BIT_AND: { | 920 case Token::BIT_AND: { |
878 VisitIntegerBitwiseOperator(expr, cache_.kIntegral32, cache_.kIntegral32, | 921 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, |
879 cache_.kInt32, false); | 922 cache_.kAsmSigned, false); |
880 return; | 923 return; |
881 } | 924 } |
882 case Token::ADD: | 925 case Token::ADD: |
883 case Token::SUB: | 926 case Token::SUB: |
884 case Token::MUL: | 927 case Token::MUL: |
885 case Token::DIV: | 928 case Token::DIV: |
886 case Token::MOD: { | 929 case Token::MOD: { |
887 RECURSE(VisitWithExpectation( | 930 RECURSE(VisitWithExpectation( |
888 expr->left(), Type::Number(), | 931 expr->left(), Type::Number(), |
889 "left arithmetic operand expected to be number")); | 932 "left arithmetic operand expected to be number")); |
890 Type* left_type = computed_type_; | 933 Type* left_type = computed_type_; |
891 int left_intish = intish_; | 934 int left_intish = intish_; |
892 RECURSE(VisitWithExpectation( | 935 RECURSE(VisitWithExpectation( |
893 expr->right(), Type::Number(), | 936 expr->right(), Type::Number(), |
894 "right arithmetic operand expected to be number")); | 937 "right arithmetic operand expected to be number")); |
895 Type* right_type = computed_type_; | 938 Type* right_type = computed_type_; |
896 int right_intish = intish_; | 939 int right_intish = intish_; |
897 Type* type = Type::Union(left_type, right_type, zone()); | 940 Type* type = Type::Union(left_type, right_type, zone()); |
898 if (type->Is(cache_.kInt32) || type->Is(cache_.kUint32)) { | 941 if (type->Is(cache_.kAsmInt)) { |
899 if (expr->op() == Token::MUL) { | 942 if (expr->op() == Token::MUL) { |
900 if (!expr->left()->IsLiteral() && !expr->right()->IsLiteral()) { | 943 Literal* right = expr->right()->AsLiteral(); |
944 if (!right) { | |
901 FAIL(expr, "direct integer multiply forbidden"); | 945 FAIL(expr, "direct integer multiply forbidden"); |
902 } | 946 } |
903 intish_ = 0; | 947 if (!right->value()->IsNumber()) { |
904 IntersectResult(expr, cache_.kInt32); | 948 FAIL(expr, "multiply must be by an integer"); |
949 } | |
950 int32_t i; | |
951 if (!right->value()->ToInt32(&i)) { | |
952 FAIL(expr, "multiply must be a signed integer"); | |
953 } | |
954 i = abs(i); | |
955 if (i >= 1 << 20) { | |
956 FAIL(expr, "multiply must be by value in -2^20 < n < 2^20"); | |
957 } | |
958 intish_ = i; | |
959 IntersectResult(expr, cache_.kAsmInt); | |
905 return; | 960 return; |
906 } else { | 961 } else { |
907 intish_ = left_intish + right_intish + 1; | 962 intish_ = left_intish + right_intish + 1; |
908 if (expr->op() == Token::ADD || expr->op() == Token::SUB) { | 963 if (expr->op() == Token::ADD || expr->op() == Token::SUB) { |
909 if (intish_ > kMaxUncombinedAdditiveSteps) { | 964 if (intish_ > kMaxUncombinedAdditiveSteps) { |
910 FAIL(expr, "too many consecutive additive ops"); | 965 FAIL(expr, "too many consecutive additive ops"); |
911 } | 966 } |
912 } else { | 967 } else { |
913 if (intish_ > kMaxUncombinedMultiplicativeSteps) { | 968 if (intish_ > kMaxUncombinedMultiplicativeSteps) { |
914 FAIL(expr, "too many consecutive multiplicative ops"); | 969 FAIL(expr, "too many consecutive multiplicative ops"); |
915 } | 970 } |
916 } | 971 } |
917 IntersectResult(expr, cache_.kInt32); | 972 IntersectResult(expr, cache_.kAsmInt); |
918 return; | 973 return; |
919 } | 974 } |
920 } else if (expr->op() == Token::MUL && | 975 } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmInt) && |
921 left_type->Is(cache_.kIntegral32) && | 976 right_type->Is(cache_.kAsmDouble)) { |
922 right_type->Is(cache_.kFloat64)) { | |
923 // For unary +, expressed as x * 1.0 | 977 // For unary +, expressed as x * 1.0 |
924 IntersectResult(expr, cache_.kFloat64); | 978 IntersectResult(expr, cache_.kAsmDouble); |
925 return; | 979 return; |
926 } else if (type->Is(cache_.kFloat32) && expr->op() != Token::MOD) { | 980 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { |
927 IntersectResult(expr, cache_.kFloat32); | 981 IntersectResult(expr, cache_.kAsmFloat); |
928 return; | 982 return; |
929 } else if (type->Is(cache_.kFloat64)) { | 983 } else if (type->Is(cache_.kAsmDouble)) { |
930 IntersectResult(expr, cache_.kFloat64); | 984 IntersectResult(expr, cache_.kAsmDouble); |
931 return; | 985 return; |
932 } else { | 986 } else { |
933 FAIL(expr, "ill-typed arithmetic operation"); | 987 FAIL(expr, "ill-typed arithmetic operation"); |
934 } | 988 } |
935 } | 989 } |
936 default: | 990 default: |
937 UNREACHABLE(); | 991 UNREACHABLE(); |
938 } | 992 } |
939 } | 993 } |
940 | 994 |
941 | 995 |
942 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { | 996 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { |
943 RECURSE( | 997 RECURSE( |
944 VisitWithExpectation(expr->left(), Type::Number(), | 998 VisitWithExpectation(expr->left(), Type::Number(), |
945 "left comparison operand expected to be number")); | 999 "left comparison operand expected to be number")); |
946 Type* left_type = computed_type_; | 1000 Type* left_type = computed_type_; |
947 RECURSE( | 1001 RECURSE( |
948 VisitWithExpectation(expr->right(), Type::Number(), | 1002 VisitWithExpectation(expr->right(), Type::Number(), |
949 "right comparison operand expected to be number")); | 1003 "right comparison operand expected to be number")); |
950 Token::Value op = expr->op(); | 1004 Token::Value op = expr->op(); |
951 if (op != Token::EQ && op != Token::NE && op != Token::LT && | 1005 if (op != Token::EQ && op != Token::NE && op != Token::LT && |
952 op != Token::LTE && op != Token::GT && op != Token::GTE) { | 1006 op != Token::LTE && op != Token::GT && op != Token::GTE) { |
953 FAIL(expr, "illegal comparison operator"); | 1007 FAIL(expr, "illegal comparison operator"); |
954 } | 1008 } |
955 Type* right_type = computed_type_; | 1009 Type* right_type = computed_type_; |
956 Type* type = Type::Union(left_type, right_type, zone()); | 1010 Type* type = Type::Union(left_type, right_type, zone()); |
957 expr->set_combined_type(type); | 1011 expr->set_combined_type(type); |
958 if (type->Is(cache_.kInt32) || type->Is(cache_.kUint32) || | 1012 if (type->Is(cache_.kAsmSigned) || type->Is(cache_.kAsmUnsigned) || |
959 type->Is(cache_.kFloat32) || type->Is(cache_.kFloat64)) { | 1013 type->Is(cache_.kAsmFloat) || type->Is(cache_.kAsmDouble)) { |
960 IntersectResult(expr, cache_.kInt32); | 1014 IntersectResult(expr, cache_.kAsmSigned); |
961 } else { | 1015 } else { |
962 FAIL(expr, "ill-typed comparison operation"); | 1016 FAIL(expr, "ill-typed comparison operation"); |
963 } | 1017 } |
964 } | 1018 } |
965 | 1019 |
966 | 1020 |
967 void AsmTyper::VisitThisFunction(ThisFunction* expr) { | 1021 void AsmTyper::VisitThisFunction(ThisFunction* expr) { |
968 FAIL(expr, "this function not allowed"); | 1022 FAIL(expr, "this function not allowed"); |
969 } | 1023 } |
970 | 1024 |
(...skipping 29 matching lines...) Expand all Loading... | |
1000 } | 1054 } |
1001 | 1055 |
1002 | 1056 |
1003 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { | 1057 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { |
1004 FAIL(expr, "call reference not allowed"); | 1058 FAIL(expr, "call reference not allowed"); |
1005 } | 1059 } |
1006 | 1060 |
1007 | 1061 |
1008 void AsmTyper::InitializeStdlib() { | 1062 void AsmTyper::InitializeStdlib() { |
1009 Type* number_type = Type::Number(zone()); | 1063 Type* number_type = Type::Number(zone()); |
1010 Type* double_type = cache_.kFloat64; | 1064 Type* double_type = cache_.kAsmDouble; |
1011 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); | 1065 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); |
1012 Type* double_fn2_type = | 1066 Type* double_fn2_type = |
1013 Type::Function(double_type, double_type, double_type, zone()); | 1067 Type::Function(double_type, double_type, double_type, zone()); |
1014 | 1068 |
1015 Type* fround_type = Type::Function(cache_.kFloat32, number_type, zone()); | 1069 Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone()); |
1016 Type* imul_type = | 1070 Type* imul_type = |
1017 Type::Function(cache_.kInt32, cache_.kInt32, cache_.kInt32, zone()); | 1071 Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone()); |
1018 // TODO(bradnelson): currently only approximating the proper intersection type | 1072 // TODO(bradnelson): currently only approximating the proper intersection type |
1019 // (which we cannot currently represent). | 1073 // (which we cannot currently represent). |
1020 Type* abs_type = Type::Function(number_type, number_type, zone()); | 1074 Type* abs_type = Type::Function(number_type, number_type, zone()); |
1021 | 1075 |
1022 struct Assignment { | 1076 struct Assignment { |
1023 const char* name; | 1077 const char* name; |
1024 Type* type; | 1078 Type* type; |
1025 }; | 1079 }; |
1026 | 1080 |
1027 const Assignment math[] = { | 1081 const Assignment math[] = { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1124 computed_type_->Print(); | 1178 computed_type_->Print(); |
1125 PrintF("Expected type: "); | 1179 PrintF("Expected type: "); |
1126 expected_type_->Print(); | 1180 expected_type_->Print(); |
1127 #endif | 1181 #endif |
1128 FAIL(expr, msg); | 1182 FAIL(expr, msg); |
1129 } | 1183 } |
1130 expected_type_ = save; | 1184 expected_type_ = save; |
1131 } | 1185 } |
1132 } // namespace internal | 1186 } // namespace internal |
1133 } // namespace v8 | 1187 } // namespace v8 |
OLD | NEW |