Chromium Code Reviews| 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 |