Home | History | Annotate | Download | only in src
      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
      3 // found in the LICENSE file.
      4 
      5 #include "src/typing-asm.h"
      6 
      7 #include <limits>
      8 
      9 #include "src/v8.h"
     10 
     11 #include "src/ast/ast.h"
     12 #include "src/ast/scopes.h"
     13 #include "src/codegen.h"
     14 #include "src/type-cache.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 #define FAIL(node, msg)                                        \
     20   do {                                                         \
     21     valid_ = false;                                            \
     22     int line = node->position() == RelocInfo::kNoPosition      \
     23                    ? -1                                        \
     24                    : script_->GetLineNumber(node->position()); \
     25     base::OS::SNPrintF(error_message_, sizeof(error_message_), \
     26                        "asm: line %d: %s\n", line + 1, msg);   \
     27     return;                                                    \
     28   } while (false)
     29 
     30 
     31 #define RECURSE(call)               \
     32   do {                              \
     33     DCHECK(!HasStackOverflow());    \
     34     call;                           \
     35     if (HasStackOverflow()) return; \
     36     if (!valid_) return;            \
     37   } while (false)
     38 
     39 
     40 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
     41                    FunctionLiteral* root)
     42     : zone_(zone),
     43       isolate_(isolate),
     44       script_(script),
     45       root_(root),
     46       valid_(true),
     47       allow_simd_(false),
     48       property_info_(NULL),
     49       intish_(0),
     50       stdlib_types_(zone),
     51       stdlib_heap_types_(zone),
     52       stdlib_math_types_(zone),
     53 #define V(NAME, Name, name, lane_count, lane_type) \
     54   stdlib_simd_##name##_types_(zone),
     55       SIMD128_TYPES(V)
     56 #undef V
     57           global_variable_type_(HashMap::PointersMatch,
     58                                 ZoneHashMap::kDefaultHashMapCapacity,
     59                                 ZoneAllocationPolicy(zone)),
     60       local_variable_type_(HashMap::PointersMatch,
     61                            ZoneHashMap::kDefaultHashMapCapacity,
     62                            ZoneAllocationPolicy(zone)),
     63       in_function_(false),
     64       building_function_tables_(false),
     65       cache_(TypeCache::Get()) {
     66   InitializeAstVisitor(isolate);
     67   InitializeStdlib();
     68 }
     69 
     70 
     71 bool AsmTyper::Validate() {
     72   VisitAsmModule(root_);
     73   return valid_ && !HasStackOverflow();
     74 }
     75 
     76 
     77 void AsmTyper::VisitAsmModule(FunctionLiteral* fun) {
     78   Scope* scope = fun->scope();
     79   if (!scope->is_function_scope()) FAIL(fun, "not at function scope");
     80 
     81   ExpressionStatement* use_asm = fun->body()->first()->AsExpressionStatement();
     82   if (use_asm == NULL) FAIL(fun, "missing \"use asm\"");
     83   Literal* use_asm_literal = use_asm->expression()->AsLiteral();
     84   if (use_asm_literal == NULL) FAIL(fun, "missing \"use asm\"");
     85   if (!use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm"))
     86     FAIL(fun, "missing \"use asm\"");
     87 
     88   // Module parameters.
     89   for (int i = 0; i < scope->num_parameters(); ++i) {
     90     Variable* param = scope->parameter(i);
     91     DCHECK(GetType(param) == NULL);
     92     SetType(param, Type::None(zone()));
     93   }
     94 
     95   ZoneList<Declaration*>* decls = scope->declarations();
     96 
     97   // Set all globals to type Any.
     98   VariableDeclaration* decl = scope->function();
     99   if (decl != NULL) SetType(decl->proxy()->var(), Type::None());
    100   RECURSE(VisitDeclarations(scope->declarations()));
    101 
    102   // Validate global variables.
    103   RECURSE(VisitStatements(fun->body()));
    104 
    105   // Validate function annotations.
    106   for (int i = 0; i < decls->length(); ++i) {
    107     FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration();
    108     if (decl != NULL) {
    109       RECURSE(VisitFunctionAnnotation(decl->fun()));
    110       Variable* var = decl->proxy()->var();
    111       if (property_info_ != NULL) {
    112         SetVariableInfo(var, property_info_);
    113         property_info_ = NULL;
    114       }
    115       SetType(var, computed_type_);
    116       DCHECK(GetType(var) != NULL);
    117     }
    118   }
    119 
    120   // Build function tables.
    121   building_function_tables_ = true;
    122   RECURSE(VisitStatements(fun->body()));
    123   building_function_tables_ = false;
    124 
    125   // Validate function bodies.
    126   for (int i = 0; i < decls->length(); ++i) {
    127     FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration();
    128     if (decl != NULL) {
    129       RECURSE(
    130           VisitWithExpectation(decl->fun(), Type::Any(zone()), "UNREACHABLE"));
    131       if (!computed_type_->IsFunction()) {
    132         FAIL(decl->fun(), "function literal expected to be a function");
    133       }
    134     }
    135   }
    136 
    137   // Validate exports.
    138   ReturnStatement* stmt = fun->body()->last()->AsReturnStatement();
    139   if (stmt == nullptr) {
    140     FAIL(fun->body()->last(), "last statement in module is not a return");
    141   }
    142   RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(),
    143                                "expected object export"));
    144 }
    145 
    146 
    147 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) {
    148   Variable* var = decl->proxy()->var();
    149   if (var->location() != VariableLocation::PARAMETER) {
    150     if (GetType(var) == NULL) {
    151       SetType(var, Type::Any(zone()));
    152     } else {
    153       DCHECK(!GetType(var)->IsFunction());
    154     }
    155   }
    156   DCHECK(GetType(var) != NULL);
    157   intish_ = 0;
    158 }
    159 
    160 
    161 void AsmTyper::VisitFunctionDeclaration(FunctionDeclaration* decl) {
    162   if (in_function_) {
    163     FAIL(decl, "function declared inside another");
    164   }
    165   // Set function type so global references to functions have some type
    166   // (so they can give a more useful error).
    167   Variable* var = decl->proxy()->var();
    168   SetType(var, Type::Function(zone()));
    169 }
    170 
    171 
    172 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) {
    173   // Extract result type.
    174   ZoneList<Statement*>* body = fun->body();
    175   Type* result_type = Type::Undefined(zone());
    176   if (body->length() > 0) {
    177     ReturnStatement* stmt = body->last()->AsReturnStatement();
    178     if (stmt != NULL) {
    179       Literal* literal = stmt->expression()->AsLiteral();
    180       Type* old_expected = expected_type_;
    181       expected_type_ = Type::Any();
    182       if (literal) {
    183         RECURSE(VisitLiteral(literal, true));
    184       } else {
    185         RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true));
    186       }
    187       expected_type_ = old_expected;
    188       result_type = computed_type_;
    189     }
    190   }
    191   Type::FunctionType* type =
    192       Type::Function(result_type, Type::Any(), fun->parameter_count(), zone())
    193           ->AsFunction();
    194 
    195   // Extract parameter types.
    196   bool good = true;
    197   for (int i = 0; i < fun->parameter_count(); ++i) {
    198     good = false;
    199     if (i >= body->length()) break;
    200     ExpressionStatement* stmt = body->at(i)->AsExpressionStatement();
    201     if (stmt == NULL) break;
    202     Assignment* expr = stmt->expression()->AsAssignment();
    203     if (expr == NULL || expr->is_compound()) break;
    204     VariableProxy* proxy = expr->target()->AsVariableProxy();
    205     if (proxy == NULL) break;
    206     Variable* var = proxy->var();
    207     if (var->location() != VariableLocation::PARAMETER || var->index() != i)
    208       break;
    209     RECURSE(VisitExpressionAnnotation(expr->value(), var, false));
    210     if (property_info_ != NULL) {
    211       SetVariableInfo(var, property_info_);
    212       property_info_ = NULL;
    213     }
    214     SetType(var, computed_type_);
    215     type->InitParameter(i, computed_type_);
    216     good = true;
    217   }
    218   if (!good) FAIL(fun, "missing parameter type annotations");
    219 
    220   SetResult(fun, type);
    221 }
    222 
    223 
    224 void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var,
    225                                          bool is_return) {
    226   // Normal +x or x|0 annotations.
    227   BinaryOperation* bin = expr->AsBinaryOperation();
    228   if (bin != NULL) {
    229     if (var != NULL) {
    230       VariableProxy* proxy = bin->left()->AsVariableProxy();
    231       if (proxy == NULL) {
    232         FAIL(bin->left(), "expected variable for type annotation");
    233       }
    234       if (proxy->var() != var) {
    235         FAIL(proxy, "annotation source doesn't match destination");
    236       }
    237     }
    238     Literal* right = bin->right()->AsLiteral();
    239     if (right != NULL) {
    240       switch (bin->op()) {
    241         case Token::MUL:  // We encode +x as x*1.0
    242           if (right->raw_value()->ContainsDot() &&
    243               right->raw_value()->AsNumber() == 1.0) {
    244             SetResult(expr, cache_.kAsmDouble);
    245             return;
    246           }
    247           break;
    248         case Token::BIT_OR:
    249           if (!right->raw_value()->ContainsDot() &&
    250               right->raw_value()->AsNumber() == 0.0) {
    251             if (is_return) {
    252               SetResult(expr, cache_.kAsmSigned);
    253             } else {
    254               SetResult(expr, cache_.kAsmInt);
    255             }
    256             return;
    257           }
    258           break;
    259         default:
    260           break;
    261       }
    262     }
    263     FAIL(expr, "invalid type annotation on binary op");
    264   }
    265 
    266   // Numbers or the undefined literal (for empty returns).
    267   if (expr->IsLiteral()) {
    268     RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal"));
    269     return;
    270   }
    271 
    272   Call* call = expr->AsCall();
    273   if (call != NULL) {
    274     VariableProxy* proxy = call->expression()->AsVariableProxy();
    275     if (proxy != NULL) {
    276       VariableInfo* info = GetVariableInfo(proxy->var(), false);
    277       if (!info ||
    278           (!info->is_check_function && !info->is_constructor_function)) {
    279         if (allow_simd_) {
    280           FAIL(call->expression(),
    281                "only fround/SIMD.checks allowed on expression annotations");
    282         } else {
    283           FAIL(call->expression(),
    284                "only fround allowed on expression annotations");
    285         }
    286       }
    287       Type* type = info->type;
    288       DCHECK(type->IsFunction());
    289       if (info->is_check_function) {
    290         DCHECK(type->AsFunction()->Arity() == 1);
    291       }
    292       if (call->arguments()->length() != type->AsFunction()->Arity()) {
    293         FAIL(call, "invalid argument count calling function");
    294       }
    295       SetResult(expr, type->AsFunction()->Result());
    296       return;
    297     }
    298   }
    299 
    300   FAIL(expr, "invalid type annotation");
    301 }
    302 
    303 
    304 void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) {
    305   for (int i = 0; i < stmts->length(); ++i) {
    306     Statement* stmt = stmts->at(i);
    307     RECURSE(Visit(stmt));
    308   }
    309 }
    310 
    311 
    312 void AsmTyper::VisitBlock(Block* stmt) {
    313   RECURSE(VisitStatements(stmt->statements()));
    314 }
    315 
    316 
    317 void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
    318   RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(),
    319                                "expression statement expected to be any"));
    320 }
    321 
    322 
    323 void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {}
    324 
    325 
    326 void AsmTyper::VisitSloppyBlockFunctionStatement(
    327     SloppyBlockFunctionStatement* stmt) {
    328   Visit(stmt->statement());
    329 }
    330 
    331 
    332 void AsmTyper::VisitEmptyParentheses(EmptyParentheses* expr) { UNREACHABLE(); }
    333 
    334 
    335 void AsmTyper::VisitIfStatement(IfStatement* stmt) {
    336   if (!in_function_) {
    337     FAIL(stmt, "if statement inside module body");
    338   }
    339   RECURSE(VisitWithExpectation(stmt->condition(), cache_.kAsmSigned,
    340                                "if condition expected to be integer"));
    341   RECURSE(Visit(stmt->then_statement()));
    342   RECURSE(Visit(stmt->else_statement()));
    343 }
    344 
    345 
    346 void AsmTyper::VisitContinueStatement(ContinueStatement* stmt) {
    347   if (!in_function_) {
    348     FAIL(stmt, "continue statement inside module body");
    349   }
    350 }
    351 
    352 
    353 void AsmTyper::VisitBreakStatement(BreakStatement* stmt) {
    354   if (!in_function_) {
    355     FAIL(stmt, "continue statement inside module body");
    356   }
    357 }
    358 
    359 
    360 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) {
    361   // Handle module return statement in VisitAsmModule.
    362   if (!in_function_) {
    363     return;
    364   }
    365   Literal* literal = stmt->expression()->AsLiteral();
    366   if (literal) {
    367     VisitLiteral(literal, true);
    368   } else {
    369     RECURSE(
    370         VisitWithExpectation(stmt->expression(), Type::Any(),
    371                              "return expression expected to have return type"));
    372   }
    373   if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) {
    374     FAIL(stmt->expression(), "return type does not match function signature");
    375   }
    376 }
    377 
    378 
    379 void AsmTyper::VisitWithStatement(WithStatement* stmt) {
    380   FAIL(stmt, "bad with statement");
    381 }
    382 
    383 
    384 void AsmTyper::VisitSwitchStatement(SwitchStatement* stmt) {
    385   if (!in_function_) {
    386     FAIL(stmt, "switch statement inside module body");
    387   }
    388   RECURSE(VisitWithExpectation(stmt->tag(), cache_.kAsmSigned,
    389                                "switch expression non-integer"));
    390   ZoneList<CaseClause*>* clauses = stmt->cases();
    391   ZoneSet<int32_t> cases(zone());
    392   for (int i = 0; i < clauses->length(); ++i) {
    393     CaseClause* clause = clauses->at(i);
    394     if (clause->is_default()) {
    395       if (i != clauses->length() - 1) {
    396         FAIL(clause, "default case out of order");
    397       }
    398     } else {
    399       Expression* label = clause->label();
    400       RECURSE(VisitWithExpectation(label, cache_.kAsmSigned,
    401                                    "case label non-integer"));
    402       if (!label->IsLiteral()) FAIL(label, "non-literal case label");
    403       Handle<Object> value = label->AsLiteral()->value();
    404       int32_t value32;
    405       if (!value->ToInt32(&value32)) FAIL(label, "illegal case label value");
    406       if (cases.find(value32) != cases.end()) {
    407         FAIL(label, "duplicate case value");
    408       }
    409       cases.insert(value32);
    410     }
    411     // TODO(bradnelson): Detect duplicates.
    412     ZoneList<Statement*>* stmts = clause->statements();
    413     RECURSE(VisitStatements(stmts));
    414   }
    415   if (cases.size() > 0) {
    416     int64_t min_case = *cases.begin();
    417     int64_t max_case = *cases.rbegin();
    418     if (max_case - min_case > std::numeric_limits<int32_t>::max()) {
    419       FAIL(stmt, "case range too large");
    420     }
    421   }
    422 }
    423 
    424 
    425 void AsmTyper::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }
    426 
    427 
    428 void AsmTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
    429   if (!in_function_) {
    430     FAIL(stmt, "do statement inside module body");
    431   }
    432   RECURSE(Visit(stmt->body()));
    433   RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
    434                                "do condition expected to be integer"));
    435 }
    436 
    437 
    438 void AsmTyper::VisitWhileStatement(WhileStatement* stmt) {
    439   if (!in_function_) {
    440     FAIL(stmt, "while statement inside module body");
    441   }
    442   RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
    443                                "while condition expected to be integer"));
    444   RECURSE(Visit(stmt->body()));
    445 }
    446 
    447 
    448 void AsmTyper::VisitForStatement(ForStatement* stmt) {
    449   if (!in_function_) {
    450     FAIL(stmt, "for statement inside module body");
    451   }
    452   if (stmt->init() != NULL) {
    453     RECURSE(Visit(stmt->init()));
    454   }
    455   if (stmt->cond() != NULL) {
    456     RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
    457                                  "for condition expected to be integer"));
    458   }
    459   if (stmt->next() != NULL) {
    460     RECURSE(Visit(stmt->next()));
    461   }
    462   RECURSE(Visit(stmt->body()));
    463 }
    464 
    465 
    466 void AsmTyper::VisitForInStatement(ForInStatement* stmt) {
    467   FAIL(stmt, "for-in statement encountered");
    468 }
    469 
    470 
    471 void AsmTyper::VisitForOfStatement(ForOfStatement* stmt) {
    472   FAIL(stmt, "for-of statement encountered");
    473 }
    474 
    475 
    476 void AsmTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
    477   FAIL(stmt, "try statement encountered");
    478 }
    479 
    480 
    481 void AsmTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
    482   FAIL(stmt, "try statement encountered");
    483 }
    484 
    485 
    486 void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
    487   FAIL(stmt, "debugger statement encountered");
    488 }
    489 
    490 
    491 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
    492   Scope* scope = expr->scope();
    493   DCHECK(scope->is_function_scope());
    494   if (in_function_) {
    495     FAIL(expr, "invalid nested function");
    496   }
    497 
    498   if (!expr->bounds().upper->IsFunction()) {
    499     FAIL(expr, "invalid function literal");
    500   }
    501 
    502   Type::FunctionType* type = expr->bounds().upper->AsFunction();
    503   Type* save_return_type = return_type_;
    504   return_type_ = type->Result();
    505   in_function_ = true;
    506   local_variable_type_.Clear();
    507   RECURSE(VisitDeclarations(scope->declarations()));
    508   RECURSE(VisitStatements(expr->body()));
    509   in_function_ = false;
    510   return_type_ = save_return_type;
    511   IntersectResult(expr, type);
    512 }
    513 
    514 
    515 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
    516   FAIL(expr, "function info literal encountered");
    517 }
    518 
    519 
    520 void AsmTyper::VisitDoExpression(DoExpression* expr) {
    521   FAIL(expr, "do-expression encountered");
    522 }
    523 
    524 
    525 void AsmTyper::VisitConditional(Conditional* expr) {
    526   RECURSE(VisitWithExpectation(expr->condition(), Type::Number(),
    527                                "condition expected to be integer"));
    528   if (!computed_type_->Is(cache_.kAsmInt)) {
    529     FAIL(expr->condition(), "condition must be of type int");
    530   }
    531 
    532   RECURSE(VisitWithExpectation(
    533       expr->then_expression(), expected_type_,
    534       "conditional then branch type mismatch with enclosing expression"));
    535   Type* then_type = StorageType(computed_type_);
    536   if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) {
    537     FAIL(expr->then_expression(), "invalid type in ? then expression");
    538   }
    539 
    540   RECURSE(VisitWithExpectation(
    541       expr->else_expression(), expected_type_,
    542       "conditional else branch type mismatch with enclosing expression"));
    543   Type* else_type = StorageType(computed_type_);
    544   if (intish_ != 0 || !else_type->Is(cache_.kAsmComparable)) {
    545     FAIL(expr->else_expression(), "invalid type in ? else expression");
    546   }
    547 
    548   if (!then_type->Is(else_type) || !else_type->Is(then_type)) {
    549     FAIL(expr, "then and else expressions in ? must have the same type");
    550   }
    551 
    552   IntersectResult(expr, then_type);
    553 }
    554 
    555 
    556 void AsmTyper::VisitVariableProxy(VariableProxy* expr) {
    557   Variable* var = expr->var();
    558   VariableInfo* info = GetVariableInfo(var, false);
    559   if (info == NULL || info->type == NULL) {
    560     if (var->mode() == TEMPORARY) {
    561       SetType(var, Type::Any(zone()));
    562       info = GetVariableInfo(var, false);
    563     } else {
    564       FAIL(expr, "unbound variable");
    565     }
    566   }
    567   if (property_info_ != NULL) {
    568     SetVariableInfo(var, property_info_);
    569     property_info_ = NULL;
    570   }
    571   Type* type = Type::Intersect(info->type, expected_type_, zone());
    572   if (type->Is(cache_.kAsmInt)) {
    573     type = cache_.kAsmInt;
    574   }
    575   info->type = type;
    576   intish_ = 0;
    577   IntersectResult(expr, type);
    578 }
    579 
    580 
    581 void AsmTyper::VisitLiteral(Literal* expr, bool is_return) {
    582   intish_ = 0;
    583   Handle<Object> value = expr->value();
    584   if (value->IsNumber()) {
    585     int32_t i;
    586     uint32_t u;
    587     if (expr->raw_value()->ContainsDot()) {
    588       IntersectResult(expr, cache_.kAsmDouble);
    589     } else if (!is_return && value->ToUint32(&u)) {
    590       if (u <= 0x7fffffff) {
    591         IntersectResult(expr, cache_.kAsmFixnum);
    592       } else {
    593         IntersectResult(expr, cache_.kAsmUnsigned);
    594       }
    595     } else if (value->ToInt32(&i)) {
    596       IntersectResult(expr, cache_.kAsmSigned);
    597     } else {
    598       FAIL(expr, "illegal number");
    599     }
    600   } else if (!is_return && value->IsString()) {
    601     IntersectResult(expr, Type::String());
    602   } else if (value->IsUndefined()) {
    603     IntersectResult(expr, Type::Undefined());
    604   } else {
    605     FAIL(expr, "illegal literal");
    606   }
    607 }
    608 
    609 
    610 void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); }
    611 
    612 
    613 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
    614   FAIL(expr, "regular expression encountered");
    615 }
    616 
    617 
    618 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) {
    619   if (in_function_) {
    620     FAIL(expr, "object literal in function");
    621   }
    622   // Allowed for asm module's export declaration.
    623   ZoneList<ObjectLiteralProperty*>* props = expr->properties();
    624   for (int i = 0; i < props->length(); ++i) {
    625     ObjectLiteralProperty* prop = props->at(i);
    626     RECURSE(VisitWithExpectation(prop->value(), Type::Any(zone()),
    627                                  "object property expected to be a function"));
    628     if (!computed_type_->IsFunction()) {
    629       FAIL(prop->value(), "non-function in function table");
    630     }
    631   }
    632   IntersectResult(expr, Type::Object(zone()));
    633 }
    634 
    635 
    636 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) {
    637   if (in_function_) {
    638     FAIL(expr, "array literal inside a function");
    639   }
    640   // Allowed for function tables.
    641   ZoneList<Expression*>* values = expr->values();
    642   Type* elem_type = Type::None(zone());
    643   for (int i = 0; i < values->length(); ++i) {
    644     Expression* value = values->at(i);
    645     RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE"));
    646     if (!computed_type_->IsFunction()) {
    647       FAIL(value, "array component expected to be a function");
    648     }
    649     elem_type = Type::Union(elem_type, computed_type_, zone());
    650   }
    651   array_size_ = values->length();
    652   IntersectResult(expr, Type::Array(elem_type, zone()));
    653 }
    654 
    655 
    656 void AsmTyper::VisitAssignment(Assignment* expr) {
    657   // Handle function tables and everything else in different passes.
    658   if (!in_function_) {
    659     if (expr->value()->IsArrayLiteral()) {
    660       if (!building_function_tables_) {
    661         return;
    662       }
    663     } else {
    664       if (building_function_tables_) {
    665         return;
    666       }
    667     }
    668   }
    669   if (expr->is_compound()) FAIL(expr, "compound assignment encountered");
    670   Type* type = expected_type_;
    671   RECURSE(VisitWithExpectation(
    672       expr->value(), type, "assignment value expected to match surrounding"));
    673   Type* target_type = StorageType(computed_type_);
    674   if (intish_ != 0) {
    675     FAIL(expr, "intish or floatish assignment");
    676   }
    677   if (expr->target()->IsVariableProxy()) {
    678     RECURSE(VisitWithExpectation(expr->target(), target_type,
    679                                  "assignment target expected to match value"));
    680   } else if (expr->target()->IsProperty()) {
    681     Property* property = expr->target()->AsProperty();
    682     RECURSE(VisitWithExpectation(property->obj(), Type::Any(),
    683                                  "bad propety object"));
    684     if (!computed_type_->IsArray()) {
    685       FAIL(property->obj(), "array expected");
    686     }
    687     VisitHeapAccess(property, true, target_type);
    688   }
    689   IntersectResult(expr, target_type);
    690 }
    691 
    692 
    693 void AsmTyper::VisitYield(Yield* expr) {
    694   FAIL(expr, "yield expression encountered");
    695 }
    696 
    697 
    698 void AsmTyper::VisitThrow(Throw* expr) {
    699   FAIL(expr, "throw statement encountered");
    700 }
    701 
    702 
    703 int AsmTyper::ElementShiftSize(Type* type) {
    704   if (type->Is(cache_.kAsmSize8)) return 0;
    705   if (type->Is(cache_.kAsmSize16)) return 1;
    706   if (type->Is(cache_.kAsmSize32)) return 2;
    707   if (type->Is(cache_.kAsmSize64)) return 3;
    708   return -1;
    709 }
    710 
    711 
    712 Type* AsmTyper::StorageType(Type* type) {
    713   if (type->Is(cache_.kAsmInt)) {
    714     return cache_.kAsmInt;
    715   } else {
    716     return type;
    717   }
    718 }
    719 
    720 
    721 void AsmTyper::VisitHeapAccess(Property* expr, bool assigning,
    722                                Type* assignment_type) {
    723   Type::ArrayType* array_type = computed_type_->AsArray();
    724   size_t size = array_size_;
    725   Type* type = array_type->AsArray()->Element();
    726   if (type->IsFunction()) {
    727     if (assigning) {
    728       FAIL(expr, "assigning to function table is illegal");
    729     }
    730     BinaryOperation* bin = expr->key()->AsBinaryOperation();
    731     if (bin == NULL || bin->op() != Token::BIT_AND) {
    732       FAIL(expr->key(), "expected & in call");
    733     }
    734     RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned,
    735                                  "array index expected to be integer"));
    736     Literal* right = bin->right()->AsLiteral();
    737     if (right == NULL || right->raw_value()->ContainsDot()) {
    738       FAIL(right, "call mask must be integer");
    739     }
    740     RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
    741                                  "call mask expected to be integer"));
    742     if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) {
    743       FAIL(right, "call mask must match function table");
    744     }
    745     bin->set_bounds(Bounds(cache_.kAsmSigned));
    746     IntersectResult(expr, type);
    747   } else {
    748     Literal* literal = expr->key()->AsLiteral();
    749     if (literal) {
    750       RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned,
    751                                    "array index expected to be integer"));
    752     } else {
    753       BinaryOperation* bin = expr->key()->AsBinaryOperation();
    754       if (bin == NULL || bin->op() != Token::SAR) {
    755         FAIL(expr->key(), "expected >> in heap access");
    756       }
    757       RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned,
    758                                    "array index expected to be integer"));
    759       Literal* right = bin->right()->AsLiteral();
    760       if (right == NULL || right->raw_value()->ContainsDot()) {
    761         FAIL(right, "heap access shift must be integer");
    762       }
    763       RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
    764                                    "array shift expected to be integer"));
    765       int n = static_cast<int>(right->raw_value()->AsNumber());
    766       int expected_shift = ElementShiftSize(type);
    767       if (expected_shift < 0 || n != expected_shift) {
    768         FAIL(right, "heap access shift must match element size");
    769       }
    770       bin->set_bounds(Bounds(cache_.kAsmSigned));
    771     }
    772     Type* result_type;
    773     if (type->Is(cache_.kAsmIntArrayElement)) {
    774       result_type = cache_.kAsmIntQ;
    775       intish_ = kMaxUncombinedAdditiveSteps;
    776     } else if (type->Is(cache_.kAsmFloat)) {
    777       if (assigning) {
    778         result_type = cache_.kAsmFloatDoubleQ;
    779       } else {
    780         result_type = cache_.kAsmFloatQ;
    781       }
    782       intish_ = 0;
    783     } else if (type->Is(cache_.kAsmDouble)) {
    784       if (assigning) {
    785         result_type = cache_.kAsmFloatDoubleQ;
    786         if (intish_ != 0) {
    787           FAIL(expr, "Assignment of floatish to Float64Array");
    788         }
    789       } else {
    790         result_type = cache_.kAsmDoubleQ;
    791       }
    792       intish_ = 0;
    793     } else {
    794       UNREACHABLE();
    795     }
    796     if (assigning) {
    797       if (!assignment_type->Is(result_type)) {
    798         FAIL(expr, "illegal type in assignment");
    799       }
    800     } else {
    801       IntersectResult(expr, expected_type_);
    802       IntersectResult(expr, result_type);
    803     }
    804   }
    805 }
    806 
    807 
    808 bool AsmTyper::IsStdlibObject(Expression* expr) {
    809   VariableProxy* proxy = expr->AsVariableProxy();
    810   if (proxy == NULL) {
    811     return false;
    812   }
    813   Variable* var = proxy->var();
    814   VariableInfo* info = GetVariableInfo(var, false);
    815   if (info) {
    816     if (info->standard_member == kStdlib) return true;
    817   }
    818   if (var->location() != VariableLocation::PARAMETER || var->index() != 0) {
    819     return false;
    820   }
    821   info = GetVariableInfo(var, true);
    822   info->type = Type::Object();
    823   info->standard_member = kStdlib;
    824   return true;
    825 }
    826 
    827 
    828 Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr,
    829                                                   const char* name) {
    830   Property* property = expr->AsProperty();
    831   if (property == NULL) {
    832     return NULL;
    833   }
    834   Literal* key = property->key()->AsLiteral();
    835   if (key == NULL || !key->IsPropertyName() ||
    836       !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) {
    837     return NULL;
    838   }
    839   return property->obj();
    840 }
    841 
    842 
    843 bool AsmTyper::IsMathObject(Expression* expr) {
    844   Expression* obj = GetReceiverOfPropertyAccess(expr, "Math");
    845   return obj && IsStdlibObject(obj);
    846 }
    847 
    848 
    849 bool AsmTyper::IsSIMDObject(Expression* expr) {
    850   Expression* obj = GetReceiverOfPropertyAccess(expr, "SIMD");
    851   return obj && IsStdlibObject(obj);
    852 }
    853 
    854 
    855 bool AsmTyper::IsSIMDTypeObject(Expression* expr, const char* name) {
    856   Expression* obj = GetReceiverOfPropertyAccess(expr, name);
    857   return obj && IsSIMDObject(obj);
    858 }
    859 
    860 
    861 void AsmTyper::VisitProperty(Property* expr) {
    862   if (IsMathObject(expr->obj())) {
    863     VisitLibraryAccess(&stdlib_math_types_, expr);
    864     return;
    865   }
    866 #define V(NAME, Name, name, lane_count, lane_type)               \
    867   if (IsSIMDTypeObject(expr->obj(), #Name)) {                    \
    868     VisitLibraryAccess(&stdlib_simd_##name##_types_, expr);      \
    869     return;                                                      \
    870   }                                                              \
    871   if (IsSIMDTypeObject(expr, #Name)) {                           \
    872     VariableInfo* info = stdlib_simd_##name##_constructor_type_; \
    873     SetResult(expr, info->type);                                 \
    874     property_info_ = info;                                       \
    875     return;                                                      \
    876   }
    877   SIMD128_TYPES(V)
    878 #undef V
    879   if (IsStdlibObject(expr->obj())) {
    880     VisitLibraryAccess(&stdlib_types_, expr);
    881     return;
    882   }
    883 
    884   property_info_ = NULL;
    885 
    886   // Only recurse at this point so that we avoid needing
    887   // stdlib.Math to have a real type.
    888   RECURSE(VisitWithExpectation(expr->obj(), Type::Any(), "bad propety object"));
    889 
    890   // For heap view or function table access.
    891   if (computed_type_->IsArray()) {
    892     VisitHeapAccess(expr, false, NULL);
    893     return;
    894   }
    895 
    896   // stdlib.x or foreign.x
    897   VariableProxy* proxy = expr->obj()->AsVariableProxy();
    898   if (proxy != NULL) {
    899     Variable* var = proxy->var();
    900     if (var->location() == VariableLocation::PARAMETER && var->index() == 1) {
    901       // foreign.x is ok.
    902       SetResult(expr, expected_type_);
    903       return;
    904     }
    905   }
    906 
    907   FAIL(expr, "invalid property access");
    908 }
    909 
    910 
    911 void AsmTyper::VisitCall(Call* expr) {
    912   RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
    913                                "callee expected to be any"));
    914   StandardMember standard_member = kNone;
    915   VariableProxy* proxy = expr->expression()->AsVariableProxy();
    916   if (proxy) {
    917     standard_member = VariableAsStandardMember(proxy->var());
    918   }
    919   if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) {
    920     FAIL(expr, "calls forbidden outside function bodies");
    921   }
    922   if (proxy == NULL && !expr->expression()->IsProperty()) {
    923     FAIL(expr, "calls must be to bound variables or function tables");
    924   }
    925   if (computed_type_->IsFunction()) {
    926     Type::FunctionType* fun_type = computed_type_->AsFunction();
    927     Type* result_type = fun_type->Result();
    928     ZoneList<Expression*>* args = expr->arguments();
    929     if (fun_type->Arity() != args->length()) {
    930       FAIL(expr, "call with wrong arity");
    931     }
    932     for (int i = 0; i < args->length(); ++i) {
    933       Expression* arg = args->at(i);
    934       RECURSE(VisitWithExpectation(
    935           arg, fun_type->Parameter(i),
    936           "call argument expected to match callee parameter"));
    937       if (standard_member != kNone && standard_member != kMathFround &&
    938           i == 0) {
    939         result_type = computed_type_;
    940       }
    941     }
    942     // Handle polymorphic stdlib functions specially.
    943     if (standard_member == kMathCeil || standard_member == kMathFloor ||
    944         standard_member == kMathSqrt) {
    945       if (!args->at(0)->bounds().upper->Is(cache_.kAsmFloat) &&
    946           !args->at(0)->bounds().upper->Is(cache_.kAsmDouble)) {
    947         FAIL(expr, "illegal function argument type");
    948       }
    949     } else if (standard_member == kMathAbs || standard_member == kMathMin ||
    950                standard_member == kMathMax) {
    951       if (!args->at(0)->bounds().upper->Is(cache_.kAsmFloat) &&
    952           !args->at(0)->bounds().upper->Is(cache_.kAsmDouble) &&
    953           !args->at(0)->bounds().upper->Is(cache_.kAsmSigned)) {
    954         FAIL(expr, "illegal function argument type");
    955       }
    956       if (args->length() > 1) {
    957         Type* other = Type::Intersect(args->at(0)->bounds().upper,
    958                                       args->at(1)->bounds().upper, zone());
    959         if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) &&
    960             !other->Is(cache_.kAsmSigned)) {
    961           FAIL(expr, "function arguments types don't match");
    962         }
    963       }
    964     }
    965     intish_ = 0;
    966     IntersectResult(expr, result_type);
    967   } else if (computed_type_->Is(Type::Any())) {
    968     // For foreign calls.
    969     ZoneList<Expression*>* args = expr->arguments();
    970     for (int i = 0; i < args->length(); ++i) {
    971       Expression* arg = args->at(i);
    972       RECURSE(VisitWithExpectation(arg, Type::Any(),
    973                                    "foreign call argument expected to be any"));
    974     }
    975     intish_ = kMaxUncombinedAdditiveSteps;
    976     IntersectResult(expr, Type::Number());
    977   } else {
    978     FAIL(expr, "invalid callee");
    979   }
    980 }
    981 
    982 
    983 void AsmTyper::VisitCallNew(CallNew* expr) {
    984   if (in_function_) {
    985     FAIL(expr, "new not allowed in module function");
    986   }
    987   RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
    988                                "expected stdlib function"));
    989   if (computed_type_->IsFunction()) {
    990     Type::FunctionType* fun_type = computed_type_->AsFunction();
    991     ZoneList<Expression*>* args = expr->arguments();
    992     if (fun_type->Arity() != args->length())
    993       FAIL(expr, "call with wrong arity");
    994     for (int i = 0; i < args->length(); ++i) {
    995       Expression* arg = args->at(i);
    996       RECURSE(VisitWithExpectation(
    997           arg, fun_type->Parameter(i),
    998           "constructor argument expected to match callee parameter"));
    999     }
   1000     IntersectResult(expr, fun_type->Result());
   1001     return;
   1002   }
   1003 
   1004   FAIL(expr, "ill-typed new operator");
   1005 }
   1006 
   1007 
   1008 void AsmTyper::VisitCallRuntime(CallRuntime* expr) {
   1009   // Allow runtime calls for now.
   1010 }
   1011 
   1012 
   1013 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) {
   1014   switch (expr->op()) {
   1015     case Token::NOT:  // Used to encode != and !==
   1016       RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt,
   1017                                    "operand expected to be integer"));
   1018       IntersectResult(expr, cache_.kAsmSigned);
   1019       return;
   1020     case Token::DELETE:
   1021       FAIL(expr, "delete operator encountered");
   1022     case Token::VOID:
   1023       FAIL(expr, "void operator encountered");
   1024     case Token::TYPEOF:
   1025       FAIL(expr, "typeof operator encountered");
   1026     default:
   1027       UNREACHABLE();
   1028   }
   1029 }
   1030 
   1031 
   1032 void AsmTyper::VisitCountOperation(CountOperation* expr) {
   1033   FAIL(expr, "increment or decrement operator encountered");
   1034 }
   1035 
   1036 
   1037 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
   1038                                            Type* left_expected,
   1039                                            Type* right_expected,
   1040                                            Type* result_type, bool conversion) {
   1041   RECURSE(VisitWithExpectation(expr->left(), Type::Number(),
   1042                                "left bitwise operand expected to be a number"));
   1043   int left_intish = intish_;
   1044   Type* left_type = computed_type_;
   1045   if (!left_type->Is(left_expected)) {
   1046     FAIL(expr->left(), "left bitwise operand expected to be an integer");
   1047   }
   1048   if (left_intish > kMaxUncombinedAdditiveSteps) {
   1049     FAIL(expr->left(), "too many consecutive additive ops");
   1050   }
   1051 
   1052   RECURSE(
   1053       VisitWithExpectation(expr->right(), Type::Number(),
   1054                            "right bitwise operand expected to be a number"));
   1055   int right_intish = intish_;
   1056   Type* right_type = computed_type_;
   1057   if (!right_type->Is(right_expected)) {
   1058     FAIL(expr->right(), "right bitwise operand expected to be an integer");
   1059   }
   1060   if (right_intish > kMaxUncombinedAdditiveSteps) {
   1061     FAIL(expr->right(), "too many consecutive additive ops");
   1062   }
   1063 
   1064   intish_ = 0;
   1065 
   1066   if (left_type->Is(cache_.kAsmFixnum) && right_type->Is(cache_.kAsmInt)) {
   1067     left_type = right_type;
   1068   }
   1069   if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) {
   1070     right_type = left_type;
   1071   }
   1072   if (!conversion) {
   1073     if (!left_type->Is(right_type) || !right_type->Is(left_type)) {
   1074       FAIL(expr, "ill-typed bitwise operation");
   1075     }
   1076   }
   1077   IntersectResult(expr, result_type);
   1078 }
   1079 
   1080 
   1081 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
   1082   switch (expr->op()) {
   1083     case Token::COMMA: {
   1084       RECURSE(VisitWithExpectation(expr->left(), Type::Any(),
   1085                                    "left comma operand expected to be any"));
   1086       RECURSE(VisitWithExpectation(expr->right(), Type::Any(),
   1087                                    "right comma operand expected to be any"));
   1088       IntersectResult(expr, computed_type_);
   1089       return;
   1090     }
   1091     case Token::OR:
   1092     case Token::AND:
   1093       FAIL(expr, "illegal logical operator");
   1094     case Token::BIT_OR: {
   1095       // BIT_OR allows Any since it is used as a type coercion.
   1096       VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt,
   1097                                   cache_.kAsmSigned, true);
   1098       return;
   1099     }
   1100     case Token::BIT_XOR: {
   1101       // Handle booleans specially to handle de-sugared !
   1102       Literal* left = expr->left()->AsLiteral();
   1103       if (left && left->value()->IsBoolean()) {
   1104         if (left->ToBooleanIsTrue()) {
   1105           left->set_bounds(Bounds(cache_.kSingletonOne));
   1106           RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt,
   1107                                        "not operator expects an integer"));
   1108           IntersectResult(expr, cache_.kAsmSigned);
   1109           return;
   1110         } else {
   1111           FAIL(left, "unexpected false");
   1112         }
   1113       }
   1114       // BIT_XOR allows Number since it is used as a type coercion (via ~~).
   1115       VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kAsmInt,
   1116                                   cache_.kAsmSigned, true);
   1117       return;
   1118     }
   1119     case Token::SHR: {
   1120       VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt,
   1121                                   cache_.kAsmUnsigned, false);
   1122       return;
   1123     }
   1124     case Token::SHL:
   1125     case Token::SAR:
   1126     case Token::BIT_AND: {
   1127       VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt,
   1128                                   cache_.kAsmSigned, false);
   1129       return;
   1130     }
   1131     case Token::ADD:
   1132     case Token::SUB:
   1133     case Token::MUL:
   1134     case Token::DIV:
   1135     case Token::MOD: {
   1136       RECURSE(VisitWithExpectation(
   1137           expr->left(), Type::Number(),
   1138           "left arithmetic operand expected to be number"));
   1139       Type* left_type = computed_type_;
   1140       int left_intish = intish_;
   1141       RECURSE(VisitWithExpectation(
   1142           expr->right(), Type::Number(),
   1143           "right arithmetic operand expected to be number"));
   1144       Type* right_type = computed_type_;
   1145       int right_intish = intish_;
   1146       Type* type = Type::Union(left_type, right_type, zone());
   1147       if (type->Is(cache_.kAsmInt)) {
   1148         if (expr->op() == Token::MUL) {
   1149           Literal* right = expr->right()->AsLiteral();
   1150           if (!right) {
   1151             FAIL(expr, "direct integer multiply forbidden");
   1152           }
   1153           if (!right->value()->IsNumber()) {
   1154             FAIL(expr, "multiply must be by an integer");
   1155           }
   1156           int32_t i;
   1157           if (!right->value()->ToInt32(&i)) {
   1158             FAIL(expr, "multiply must be a signed integer");
   1159           }
   1160           i = abs(i);
   1161           if (i >= 1 << 20) {
   1162             FAIL(expr, "multiply must be by value in -2^20 < n < 2^20");
   1163           }
   1164           intish_ = i;
   1165           IntersectResult(expr, cache_.kAsmInt);
   1166           return;
   1167         } else {
   1168           intish_ = left_intish + right_intish + 1;
   1169           if (expr->op() == Token::ADD || expr->op() == Token::SUB) {
   1170             if (intish_ > kMaxUncombinedAdditiveSteps) {
   1171               FAIL(expr, "too many consecutive additive ops");
   1172             }
   1173           } else {
   1174             if (intish_ > kMaxUncombinedMultiplicativeSteps) {
   1175               FAIL(expr, "too many consecutive multiplicative ops");
   1176             }
   1177           }
   1178           IntersectResult(expr, cache_.kAsmInt);
   1179           return;
   1180         }
   1181       } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() &&
   1182                  right_type->Is(cache_.kAsmDouble)) {
   1183         // For unary +, expressed as x * 1.0
   1184         IntersectResult(expr, cache_.kAsmDouble);
   1185         return;
   1186       } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) {
   1187         if (left_intish != 0 || right_intish != 0) {
   1188           FAIL(expr, "float operation before required fround");
   1189         }
   1190         IntersectResult(expr, cache_.kAsmFloat);
   1191         intish_ = 1;
   1192         return;
   1193       } else if (type->Is(cache_.kAsmDouble)) {
   1194         IntersectResult(expr, cache_.kAsmDouble);
   1195         return;
   1196       } else {
   1197         FAIL(expr, "ill-typed arithmetic operation");
   1198       }
   1199     }
   1200     default:
   1201       UNREACHABLE();
   1202   }
   1203 }
   1204 
   1205 
   1206 void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
   1207   Token::Value op = expr->op();
   1208   if (op != Token::EQ && op != Token::NE && op != Token::LT &&
   1209       op != Token::LTE && op != Token::GT && op != Token::GTE) {
   1210     FAIL(expr, "illegal comparison operator");
   1211   }
   1212 
   1213   RECURSE(
   1214       VisitWithExpectation(expr->left(), Type::Number(),
   1215                            "left comparison operand expected to be number"));
   1216   Type* left_type = computed_type_;
   1217   if (!left_type->Is(cache_.kAsmComparable)) {
   1218     FAIL(expr->left(), "bad type on left side of comparison");
   1219   }
   1220 
   1221   RECURSE(
   1222       VisitWithExpectation(expr->right(), Type::Number(),
   1223                            "right comparison operand expected to be number"));
   1224   Type* right_type = computed_type_;
   1225   if (!right_type->Is(cache_.kAsmComparable)) {
   1226     FAIL(expr->right(), "bad type on right side of comparison");
   1227   }
   1228 
   1229   if (!left_type->Is(right_type) && !right_type->Is(left_type)) {
   1230     FAIL(expr, "left and right side of comparison must match");
   1231   }
   1232 
   1233   IntersectResult(expr, cache_.kAsmSigned);
   1234 }
   1235 
   1236 
   1237 void AsmTyper::VisitThisFunction(ThisFunction* expr) {
   1238   FAIL(expr, "this function not allowed");
   1239 }
   1240 
   1241 
   1242 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
   1243   for (int i = 0; i < decls->length(); ++i) {
   1244     Declaration* decl = decls->at(i);
   1245     RECURSE(Visit(decl));
   1246   }
   1247 }
   1248 
   1249 
   1250 void AsmTyper::VisitImportDeclaration(ImportDeclaration* decl) {
   1251   FAIL(decl, "import declaration encountered");
   1252 }
   1253 
   1254 
   1255 void AsmTyper::VisitExportDeclaration(ExportDeclaration* decl) {
   1256   FAIL(decl, "export declaration encountered");
   1257 }
   1258 
   1259 
   1260 void AsmTyper::VisitClassLiteral(ClassLiteral* expr) {
   1261   FAIL(expr, "class literal not allowed");
   1262 }
   1263 
   1264 
   1265 void AsmTyper::VisitSpread(Spread* expr) { FAIL(expr, "spread not allowed"); }
   1266 
   1267 
   1268 void AsmTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) {
   1269   FAIL(expr, "super property reference not allowed");
   1270 }
   1271 
   1272 
   1273 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) {
   1274   FAIL(expr, "call reference not allowed");
   1275 }
   1276 
   1277 
   1278 void AsmTyper::InitializeStdlibSIMD() {
   1279 #define V(NAME, Name, name, lane_count, lane_type)                            \
   1280   {                                                                           \
   1281     Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(),    \
   1282                                 lane_count, zone());                          \
   1283     for (int i = 0; i < lane_count; ++i) {                                    \
   1284       type->AsFunction()->InitParameter(i, Type::Number());                   \
   1285     }                                                                         \
   1286     stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \
   1287     stdlib_simd_##name##_constructor_type_->is_constructor_function = true;   \
   1288   }
   1289   SIMD128_TYPES(V)
   1290 #undef V
   1291 }
   1292 
   1293 
   1294 void AsmTyper::InitializeStdlib() {
   1295   if (allow_simd_) {
   1296     InitializeStdlibSIMD();
   1297   }
   1298   Type* number_type = Type::Number(zone());
   1299   Type* double_type = cache_.kAsmDouble;
   1300   Type* double_fn1_type = Type::Function(double_type, double_type, zone());
   1301   Type* double_fn2_type =
   1302       Type::Function(double_type, double_type, double_type, zone());
   1303 
   1304   Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone());
   1305   Type* imul_type =
   1306       Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone());
   1307   // TODO(bradnelson): currently only approximating the proper intersection type
   1308   // (which we cannot currently represent).
   1309   Type* number_fn1_type = Type::Function(number_type, number_type, zone());
   1310   Type* number_fn2_type =
   1311       Type::Function(number_type, number_type, number_type, zone());
   1312 
   1313   struct Assignment {
   1314     const char* name;
   1315     StandardMember standard_member;
   1316     Type* type;
   1317   };
   1318 
   1319   const Assignment math[] = {{"PI", kMathPI, double_type},
   1320                              {"E", kMathE, double_type},
   1321                              {"LN2", kMathLN2, double_type},
   1322                              {"LN10", kMathLN10, double_type},
   1323                              {"LOG2E", kMathLOG2E, double_type},
   1324                              {"LOG10E", kMathLOG10E, double_type},
   1325                              {"SQRT2", kMathSQRT2, double_type},
   1326                              {"SQRT1_2", kMathSQRT1_2, double_type},
   1327                              {"imul", kMathImul, imul_type},
   1328                              {"abs", kMathAbs, number_fn1_type},
   1329                              {"ceil", kMathCeil, number_fn1_type},
   1330                              {"floor", kMathFloor, number_fn1_type},
   1331                              {"fround", kMathFround, fround_type},
   1332                              {"pow", kMathPow, double_fn2_type},
   1333                              {"exp", kMathExp, double_fn1_type},
   1334                              {"log", kMathLog, double_fn1_type},
   1335                              {"min", kMathMin, number_fn2_type},
   1336                              {"max", kMathMax, number_fn2_type},
   1337                              {"sqrt", kMathSqrt, number_fn1_type},
   1338                              {"cos", kMathCos, double_fn1_type},
   1339                              {"sin", kMathSin, double_fn1_type},
   1340                              {"tan", kMathTan, double_fn1_type},
   1341                              {"acos", kMathAcos, double_fn1_type},
   1342                              {"asin", kMathAsin, double_fn1_type},
   1343                              {"atan", kMathAtan, double_fn1_type},
   1344                              {"atan2", kMathAtan2, double_fn2_type}};
   1345   for (unsigned i = 0; i < arraysize(math); ++i) {
   1346     stdlib_math_types_[math[i].name] = new (zone()) VariableInfo(math[i].type);
   1347     stdlib_math_types_[math[i].name]->standard_member = math[i].standard_member;
   1348   }
   1349   stdlib_math_types_["fround"]->is_check_function = true;
   1350 
   1351   stdlib_types_["Infinity"] = new (zone()) VariableInfo(double_type);
   1352   stdlib_types_["Infinity"]->standard_member = kInfinity;
   1353   stdlib_types_["NaN"] = new (zone()) VariableInfo(double_type);
   1354   stdlib_types_["NaN"]->standard_member = kNaN;
   1355   Type* buffer_type = Type::Any(zone());
   1356 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
   1357   stdlib_types_[#TypeName "Array"] = new (zone()) VariableInfo(  \
   1358       Type::Function(cache_.k##TypeName##Array, buffer_type, zone()));
   1359   TYPED_ARRAYS(TYPED_ARRAY)
   1360 #undef TYPED_ARRAY
   1361 
   1362 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size)     \
   1363   stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \
   1364       Type::Function(cache_.k##TypeName##Array, buffer_type, zone()));
   1365   TYPED_ARRAYS(TYPED_ARRAY)
   1366 #undef TYPED_ARRAY
   1367 }
   1368 
   1369 
   1370 void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) {
   1371   Literal* key = expr->key()->AsLiteral();
   1372   if (key == NULL || !key->IsPropertyName())
   1373     FAIL(expr, "invalid key used on stdlib member");
   1374   Handle<String> name = key->AsPropertyName();
   1375   VariableInfo* info = LibType(map, name);
   1376   if (info == NULL || info->type == NULL) FAIL(expr, "unknown stdlib function");
   1377   SetResult(expr, info->type);
   1378   property_info_ = info;
   1379 }
   1380 
   1381 
   1382 AsmTyper::VariableInfo* AsmTyper::LibType(ObjectTypeMap* map,
   1383                                           Handle<String> name) {
   1384   base::SmartArrayPointer<char> aname = name->ToCString();
   1385   ObjectTypeMap::iterator i = map->find(std::string(aname.get()));
   1386   if (i == map->end()) {
   1387     return NULL;
   1388   }
   1389   return i->second;
   1390 }
   1391 
   1392 
   1393 void AsmTyper::SetType(Variable* variable, Type* type) {
   1394   VariableInfo* info = GetVariableInfo(variable, true);
   1395   info->type = type;
   1396 }
   1397 
   1398 
   1399 Type* AsmTyper::GetType(Variable* variable) {
   1400   VariableInfo* info = GetVariableInfo(variable, false);
   1401   if (!info) return NULL;
   1402   return info->type;
   1403 }
   1404 
   1405 
   1406 AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable,
   1407                                                   bool setting) {
   1408   ZoneHashMap::Entry* entry;
   1409   ZoneHashMap* map;
   1410   if (in_function_) {
   1411     map = &local_variable_type_;
   1412   } else {
   1413     map = &global_variable_type_;
   1414   }
   1415   if (setting) {
   1416     entry = map->LookupOrInsert(variable, ComputePointerHash(variable),
   1417                                 ZoneAllocationPolicy(zone()));
   1418   } else {
   1419     entry = map->Lookup(variable, ComputePointerHash(variable));
   1420     if (!entry && in_function_) {
   1421       entry =
   1422           global_variable_type_.Lookup(variable, ComputePointerHash(variable));
   1423       if (entry && entry->value) {
   1424       }
   1425     }
   1426   }
   1427   if (!entry) return NULL;
   1428   if (!entry->value) {
   1429     if (!setting) return NULL;
   1430     entry->value = new (zone()) VariableInfo;
   1431   }
   1432   return reinterpret_cast<VariableInfo*>(entry->value);
   1433 }
   1434 
   1435 
   1436 void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) {
   1437   VariableInfo* dest = GetVariableInfo(variable, true);
   1438   dest->type = info->type;
   1439   dest->is_check_function = info->is_check_function;
   1440   dest->is_constructor_function = info->is_constructor_function;
   1441   dest->standard_member = info->standard_member;
   1442 }
   1443 
   1444 
   1445 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(
   1446     Variable* variable) {
   1447   VariableInfo* info = GetVariableInfo(variable, false);
   1448   if (!info) return kNone;
   1449   return info->standard_member;
   1450 }
   1451 
   1452 
   1453 void AsmTyper::SetResult(Expression* expr, Type* type) {
   1454   computed_type_ = type;
   1455   expr->set_bounds(Bounds(computed_type_));
   1456 }
   1457 
   1458 
   1459 void AsmTyper::IntersectResult(Expression* expr, Type* type) {
   1460   computed_type_ = type;
   1461   Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
   1462   expr->set_bounds(Bounds(bounded_type));
   1463 }
   1464 
   1465 
   1466 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type,
   1467                                     const char* msg) {
   1468   Type* save = expected_type_;
   1469   expected_type_ = expected_type;
   1470   RECURSE(Visit(expr));
   1471   Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
   1472   if (bounded_type->Is(Type::None(zone()))) {
   1473 #ifdef DEBUG
   1474     PrintF("Computed type: ");
   1475     computed_type_->Print();
   1476     PrintF("Expected type: ");
   1477     expected_type_->Print();
   1478 #endif
   1479     FAIL(expr, msg);
   1480   }
   1481   expected_type_ = save;
   1482 }
   1483 
   1484 
   1485 void AsmTyper::VisitRewritableAssignmentExpression(
   1486     RewritableAssignmentExpression* expr) {
   1487   RECURSE(Visit(expr->expression()));
   1488 }
   1489 
   1490 
   1491 }  // namespace internal
   1492 }  // namespace v8
   1493