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