blob: e541539a78329622030aea37dcb3556c31d05458 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
16namespace v8 {
17namespace 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
40 FunctionLiteral* root)
41 : zone_(zone),
42 isolate_(isolate),
43 script_(script),
44 root_(root),
45 valid_(true),
46 allow_simd_(false),
Ben Murdochc5610432016-08-08 18:44:38 +010047 property_info_(nullptr),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000048 intish_(0),
49 stdlib_types_(zone),
50 stdlib_heap_types_(zone),
51 stdlib_math_types_(zone),
52#define V(NAME, Name, name, lane_count, lane_type) \
53 stdlib_simd_##name##_types_(zone),
54 SIMD128_TYPES(V)
55#undef V
56 global_variable_type_(HashMap::PointersMatch,
57 ZoneHashMap::kDefaultHashMapCapacity,
58 ZoneAllocationPolicy(zone)),
59 local_variable_type_(HashMap::PointersMatch,
60 ZoneHashMap::kDefaultHashMapCapacity,
61 ZoneAllocationPolicy(zone)),
62 in_function_(false),
63 building_function_tables_(false),
Ben Murdoch097c5b22016-05-18 11:27:45 +010064 visiting_exports_(false),
Ben Murdochc5610432016-08-08 18:44:38 +010065 cache_(TypeCache::Get()),
66 bounds_(zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 InitializeAstVisitor(isolate);
68 InitializeStdlib();
69}
70
71
72bool AsmTyper::Validate() {
73 VisitAsmModule(root_);
74 return valid_ && !HasStackOverflow();
75}
76
77
78void AsmTyper::VisitAsmModule(FunctionLiteral* fun) {
79 Scope* scope = fun->scope();
80 if (!scope->is_function_scope()) FAIL(fun, "not at function scope");
81
82 ExpressionStatement* use_asm = fun->body()->first()->AsExpressionStatement();
Ben Murdochc5610432016-08-08 18:44:38 +010083 if (use_asm == nullptr) FAIL(fun, "missing \"use asm\"");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084 Literal* use_asm_literal = use_asm->expression()->AsLiteral();
Ben Murdochc5610432016-08-08 18:44:38 +010085 if (use_asm_literal == nullptr) FAIL(fun, "missing \"use asm\"");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086 if (!use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm"))
87 FAIL(fun, "missing \"use asm\"");
88
89 // Module parameters.
90 for (int i = 0; i < scope->num_parameters(); ++i) {
91 Variable* param = scope->parameter(i);
Ben Murdochc5610432016-08-08 18:44:38 +010092 DCHECK(GetType(param) == nullptr);
Ben Murdoch097c5b22016-05-18 11:27:45 +010093 SetType(param, Type::None());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094 }
95
96 ZoneList<Declaration*>* decls = scope->declarations();
97
98 // Set all globals to type Any.
99 VariableDeclaration* decl = scope->function();
Ben Murdochc5610432016-08-08 18:44:38 +0100100 if (decl != nullptr) SetType(decl->proxy()->var(), Type::None());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000101 RECURSE(VisitDeclarations(scope->declarations()));
102
103 // Validate global variables.
104 RECURSE(VisitStatements(fun->body()));
105
106 // Validate function annotations.
107 for (int i = 0; i < decls->length(); ++i) {
108 FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration();
Ben Murdochc5610432016-08-08 18:44:38 +0100109 if (decl != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110 RECURSE(VisitFunctionAnnotation(decl->fun()));
111 Variable* var = decl->proxy()->var();
Ben Murdochc5610432016-08-08 18:44:38 +0100112 if (property_info_ != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113 SetVariableInfo(var, property_info_);
Ben Murdochc5610432016-08-08 18:44:38 +0100114 property_info_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 }
116 SetType(var, computed_type_);
Ben Murdochc5610432016-08-08 18:44:38 +0100117 DCHECK(GetType(var) != nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 }
119 }
120
121 // Build function tables.
122 building_function_tables_ = true;
123 RECURSE(VisitStatements(fun->body()));
124 building_function_tables_ = false;
125
126 // Validate function bodies.
127 for (int i = 0; i < decls->length(); ++i) {
128 FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration();
Ben Murdochc5610432016-08-08 18:44:38 +0100129 if (decl != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100130 RECURSE(VisitWithExpectation(decl->fun(), Type::Any(), "UNREACHABLE"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 if (!computed_type_->IsFunction()) {
132 FAIL(decl->fun(), "function literal expected to be a function");
133 }
134 }
135 }
136
137 // Validate exports.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100138 visiting_exports_ = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 ReturnStatement* stmt = fun->body()->last()->AsReturnStatement();
140 if (stmt == nullptr) {
141 FAIL(fun->body()->last(), "last statement in module is not a return");
142 }
143 RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(),
144 "expected object export"));
145}
146
147
148void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) {
149 Variable* var = decl->proxy()->var();
150 if (var->location() != VariableLocation::PARAMETER) {
Ben Murdochc5610432016-08-08 18:44:38 +0100151 if (GetType(var) == nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100152 SetType(var, Type::Any());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153 } else {
154 DCHECK(!GetType(var)->IsFunction());
155 }
156 }
Ben Murdochc5610432016-08-08 18:44:38 +0100157 DCHECK(GetType(var) != nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000158 intish_ = 0;
159}
160
161
162void AsmTyper::VisitFunctionDeclaration(FunctionDeclaration* decl) {
163 if (in_function_) {
164 FAIL(decl, "function declared inside another");
165 }
166 // Set function type so global references to functions have some type
167 // (so they can give a more useful error).
168 Variable* var = decl->proxy()->var();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100169 SetType(var, Type::Function());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170}
171
172
173void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) {
174 // Extract result type.
175 ZoneList<Statement*>* body = fun->body();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100176 Type* result_type = Type::Undefined();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177 if (body->length() > 0) {
178 ReturnStatement* stmt = body->last()->AsReturnStatement();
Ben Murdochc5610432016-08-08 18:44:38 +0100179 if (stmt != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 Literal* literal = stmt->expression()->AsLiteral();
181 Type* old_expected = expected_type_;
182 expected_type_ = Type::Any();
183 if (literal) {
184 RECURSE(VisitLiteral(literal, true));
185 } else {
Ben Murdochc5610432016-08-08 18:44:38 +0100186 RECURSE(VisitExpressionAnnotation(stmt->expression(), nullptr, true));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 }
188 expected_type_ = old_expected;
189 result_type = computed_type_;
190 }
191 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100192 Type* type =
193 Type::Function(result_type, Type::Any(), fun->parameter_count(), zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194
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();
Ben Murdochc5610432016-08-08 18:44:38 +0100201 if (stmt == nullptr) break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 Assignment* expr = stmt->expression()->AsAssignment();
Ben Murdochc5610432016-08-08 18:44:38 +0100203 if (expr == nullptr || expr->is_compound()) break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 VariableProxy* proxy = expr->target()->AsVariableProxy();
Ben Murdochc5610432016-08-08 18:44:38 +0100205 if (proxy == nullptr) break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 Variable* var = proxy->var();
207 if (var->location() != VariableLocation::PARAMETER || var->index() != i)
208 break;
209 RECURSE(VisitExpressionAnnotation(expr->value(), var, false));
Ben Murdochc5610432016-08-08 18:44:38 +0100210 if (property_info_ != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 SetVariableInfo(var, property_info_);
Ben Murdochc5610432016-08-08 18:44:38 +0100212 property_info_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213 }
214 SetType(var, computed_type_);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100215 type->AsFunction()->InitParameter(i, computed_type_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 good = true;
217 }
218 if (!good) FAIL(fun, "missing parameter type annotations");
219
220 SetResult(fun, type);
221}
222
223
224void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var,
225 bool is_return) {
226 // Normal +x or x|0 annotations.
227 BinaryOperation* bin = expr->AsBinaryOperation();
Ben Murdochc5610432016-08-08 18:44:38 +0100228 if (bin != nullptr) {
229 if (var != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 VariableProxy* proxy = bin->left()->AsVariableProxy();
Ben Murdochc5610432016-08-08 18:44:38 +0100231 if (proxy == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 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();
Ben Murdochc5610432016-08-08 18:44:38 +0100239 if (right != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 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();
Ben Murdochc5610432016-08-08 18:44:38 +0100273 if (call != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274 VariableProxy* proxy = call->expression()->AsVariableProxy();
Ben Murdochc5610432016-08-08 18:44:38 +0100275 if (proxy != nullptr) {
276 VariableInfo* info = GetVariableInfo(proxy->var());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 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
304void 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
312void AsmTyper::VisitBlock(Block* stmt) {
313 RECURSE(VisitStatements(stmt->statements()));
314}
315
316
317void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
318 RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(),
319 "expression statement expected to be any"));
320}
321
322
323void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {}
324
325
326void AsmTyper::VisitSloppyBlockFunctionStatement(
327 SloppyBlockFunctionStatement* stmt) {
328 Visit(stmt->statement());
329}
330
331
332void AsmTyper::VisitEmptyParentheses(EmptyParentheses* expr) { UNREACHABLE(); }
333
334
335void 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
346void AsmTyper::VisitContinueStatement(ContinueStatement* stmt) {
347 if (!in_function_) {
348 FAIL(stmt, "continue statement inside module body");
349 }
350}
351
352
353void AsmTyper::VisitBreakStatement(BreakStatement* stmt) {
354 if (!in_function_) {
355 FAIL(stmt, "continue statement inside module body");
356 }
357}
358
359
360void 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
379void AsmTyper::VisitWithStatement(WithStatement* stmt) {
380 FAIL(stmt, "bad with statement");
381}
382
383
384void 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
425void AsmTyper::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }
426
427
428void 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
438void 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
448void AsmTyper::VisitForStatement(ForStatement* stmt) {
449 if (!in_function_) {
450 FAIL(stmt, "for statement inside module body");
451 }
Ben Murdochc5610432016-08-08 18:44:38 +0100452 if (stmt->init() != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 RECURSE(Visit(stmt->init()));
454 }
Ben Murdochc5610432016-08-08 18:44:38 +0100455 if (stmt->cond() != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000456 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
457 "for condition expected to be integer"));
458 }
Ben Murdochc5610432016-08-08 18:44:38 +0100459 if (stmt->next() != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 RECURSE(Visit(stmt->next()));
461 }
462 RECURSE(Visit(stmt->body()));
463}
464
465
466void AsmTyper::VisitForInStatement(ForInStatement* stmt) {
467 FAIL(stmt, "for-in statement encountered");
468}
469
470
471void AsmTyper::VisitForOfStatement(ForOfStatement* stmt) {
472 FAIL(stmt, "for-of statement encountered");
473}
474
475
476void AsmTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
477 FAIL(stmt, "try statement encountered");
478}
479
480
481void AsmTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
482 FAIL(stmt, "try statement encountered");
483}
484
485
486void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
487 FAIL(stmt, "debugger statement encountered");
488}
489
490
491void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000492 if (in_function_) {
493 FAIL(expr, "invalid nested function");
494 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100495 Scope* scope = expr->scope();
496 DCHECK(scope->is_function_scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497
Ben Murdochc5610432016-08-08 18:44:38 +0100498 if (!bounds_.get(expr).upper->IsFunction()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 FAIL(expr, "invalid function literal");
500 }
501
Ben Murdochc5610432016-08-08 18:44:38 +0100502 Type* type = bounds_.get(expr).upper;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503 Type* save_return_type = return_type_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100504 return_type_ = type->AsFunction()->Result();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000505 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
515void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
516 FAIL(expr, "function info literal encountered");
517}
518
519
520void AsmTyper::VisitDoExpression(DoExpression* expr) {
521 FAIL(expr, "do-expression encountered");
522}
523
524
525void AsmTyper::VisitConditional(Conditional* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100526 if (!in_function_) {
527 FAIL(expr, "ternary operator inside module body");
528 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(),
530 "condition expected to be integer"));
531 if (!computed_type_->Is(cache_.kAsmInt)) {
532 FAIL(expr->condition(), "condition must be of type int");
533 }
534
535 RECURSE(VisitWithExpectation(
536 expr->then_expression(), expected_type_,
537 "conditional then branch type mismatch with enclosing expression"));
538 Type* then_type = StorageType(computed_type_);
539 if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) {
540 FAIL(expr->then_expression(), "invalid type in ? then expression");
541 }
542
543 RECURSE(VisitWithExpectation(
544 expr->else_expression(), expected_type_,
545 "conditional else branch type mismatch with enclosing expression"));
546 Type* else_type = StorageType(computed_type_);
547 if (intish_ != 0 || !else_type->Is(cache_.kAsmComparable)) {
548 FAIL(expr->else_expression(), "invalid type in ? else expression");
549 }
550
551 if (!then_type->Is(else_type) || !else_type->Is(then_type)) {
552 FAIL(expr, "then and else expressions in ? must have the same type");
553 }
554
555 IntersectResult(expr, then_type);
556}
557
558
559void AsmTyper::VisitVariableProxy(VariableProxy* expr) {
560 Variable* var = expr->var();
Ben Murdochc5610432016-08-08 18:44:38 +0100561 VariableInfo* info = GetVariableInfo(var);
562 if (!in_function_ && !building_function_tables_ && !visiting_exports_) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100563 if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) {
564 FAIL(expr, "illegal variable reference in module body");
565 }
566 }
Ben Murdochc5610432016-08-08 18:44:38 +0100567 if (info == nullptr || info->type == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 if (var->mode() == TEMPORARY) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100569 SetType(var, Type::Any());
Ben Murdochc5610432016-08-08 18:44:38 +0100570 info = GetVariableInfo(var);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000571 } else {
572 FAIL(expr, "unbound variable");
573 }
574 }
Ben Murdochc5610432016-08-08 18:44:38 +0100575 if (property_info_ != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 SetVariableInfo(var, property_info_);
Ben Murdochc5610432016-08-08 18:44:38 +0100577 property_info_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578 }
579 Type* type = Type::Intersect(info->type, expected_type_, zone());
Ben Murdochc5610432016-08-08 18:44:38 +0100580 if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581 intish_ = 0;
582 IntersectResult(expr, type);
583}
584
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585void AsmTyper::VisitLiteral(Literal* expr, bool is_return) {
586 intish_ = 0;
587 Handle<Object> value = expr->value();
588 if (value->IsNumber()) {
589 int32_t i;
590 uint32_t u;
591 if (expr->raw_value()->ContainsDot()) {
592 IntersectResult(expr, cache_.kAsmDouble);
593 } else if (!is_return && value->ToUint32(&u)) {
594 if (u <= 0x7fffffff) {
595 IntersectResult(expr, cache_.kAsmFixnum);
596 } else {
597 IntersectResult(expr, cache_.kAsmUnsigned);
598 }
599 } else if (value->ToInt32(&i)) {
600 IntersectResult(expr, cache_.kAsmSigned);
601 } else {
602 FAIL(expr, "illegal number");
603 }
604 } else if (!is_return && value->IsString()) {
605 IntersectResult(expr, Type::String());
606 } else if (value->IsUndefined()) {
607 IntersectResult(expr, Type::Undefined());
608 } else {
609 FAIL(expr, "illegal literal");
610 }
611}
612
613
614void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); }
615
616
617void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
618 FAIL(expr, "regular expression encountered");
619}
620
621
622void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) {
623 if (in_function_) {
624 FAIL(expr, "object literal in function");
625 }
626 // Allowed for asm module's export declaration.
627 ZoneList<ObjectLiteralProperty*>* props = expr->properties();
628 for (int i = 0; i < props->length(); ++i) {
629 ObjectLiteralProperty* prop = props->at(i);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100630 RECURSE(VisitWithExpectation(prop->value(), Type::Any(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000631 "object property expected to be a function"));
632 if (!computed_type_->IsFunction()) {
633 FAIL(prop->value(), "non-function in function table");
634 }
635 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100636 IntersectResult(expr, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637}
638
639
640void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) {
641 if (in_function_) {
642 FAIL(expr, "array literal inside a function");
643 }
644 // Allowed for function tables.
645 ZoneList<Expression*>* values = expr->values();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100646 Type* elem_type = Type::None();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647 for (int i = 0; i < values->length(); ++i) {
648 Expression* value = values->at(i);
649 RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE"));
650 if (!computed_type_->IsFunction()) {
651 FAIL(value, "array component expected to be a function");
652 }
653 elem_type = Type::Union(elem_type, computed_type_, zone());
654 }
655 array_size_ = values->length();
656 IntersectResult(expr, Type::Array(elem_type, zone()));
657}
658
659
660void AsmTyper::VisitAssignment(Assignment* expr) {
661 // Handle function tables and everything else in different passes.
662 if (!in_function_) {
663 if (expr->value()->IsArrayLiteral()) {
664 if (!building_function_tables_) {
665 return;
666 }
667 } else {
668 if (building_function_tables_) {
669 return;
670 }
671 }
672 }
673 if (expr->is_compound()) FAIL(expr, "compound assignment encountered");
674 Type* type = expected_type_;
675 RECURSE(VisitWithExpectation(
676 expr->value(), type, "assignment value expected to match surrounding"));
677 Type* target_type = StorageType(computed_type_);
Ben Murdochc5610432016-08-08 18:44:38 +0100678
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679 if (expr->target()->IsVariableProxy()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100680 // Assignment to a local or context variable.
681 VariableProxy* proxy = expr->target()->AsVariableProxy();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100682 if (intish_ != 0) {
683 FAIL(expr, "intish or floatish assignment");
684 }
685 expected_type_ = target_type;
Ben Murdochc5610432016-08-08 18:44:38 +0100686 Variable* var = proxy->var();
687 VariableInfo* info = GetVariableInfo(var);
688 if (info == nullptr || info->type == nullptr) {
689 if (var->mode() == TEMPORARY) {
690 SetType(var, Type::Any());
691 info = GetVariableInfo(var);
692 } else {
693 FAIL(proxy, "unbound variable");
694 }
695 }
696 if (property_info_ != nullptr) {
697 SetVariableInfo(var, property_info_);
698 property_info_ = nullptr;
699 }
700 Type* type = Type::Intersect(info->type, expected_type_, zone());
701 if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt;
702 info->type = type;
703 intish_ = 0;
704 IntersectResult(proxy, type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000705 } else if (expr->target()->IsProperty()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100706 // Assignment to a property: should be a heap assignment {H[x] = y}.
Ben Murdochda12d292016-06-02 14:46:10 +0100707 int32_t value_intish = intish_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000708 Property* property = expr->target()->AsProperty();
709 RECURSE(VisitWithExpectation(property->obj(), Type::Any(),
710 "bad propety object"));
711 if (!computed_type_->IsArray()) {
712 FAIL(property->obj(), "array expected");
713 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100714 if (value_intish != 0 && computed_type_->Is(cache_.kFloat64Array)) {
715 FAIL(expr, "floatish assignment to double array");
716 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000717 VisitHeapAccess(property, true, target_type);
718 }
719 IntersectResult(expr, target_type);
720}
721
722
723void AsmTyper::VisitYield(Yield* expr) {
724 FAIL(expr, "yield expression encountered");
725}
726
727
728void AsmTyper::VisitThrow(Throw* expr) {
729 FAIL(expr, "throw statement encountered");
730}
731
732
733int AsmTyper::ElementShiftSize(Type* type) {
734 if (type->Is(cache_.kAsmSize8)) return 0;
735 if (type->Is(cache_.kAsmSize16)) return 1;
736 if (type->Is(cache_.kAsmSize32)) return 2;
737 if (type->Is(cache_.kAsmSize64)) return 3;
738 return -1;
739}
740
741
742Type* AsmTyper::StorageType(Type* type) {
743 if (type->Is(cache_.kAsmInt)) {
744 return cache_.kAsmInt;
745 } else {
746 return type;
747 }
748}
749
750
751void AsmTyper::VisitHeapAccess(Property* expr, bool assigning,
752 Type* assignment_type) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100753 ArrayType* array_type = computed_type_->AsArray();
754 // size_t size = array_size_;
755 Type* type = array_type->Element();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000756 if (type->IsFunction()) {
757 if (assigning) {
758 FAIL(expr, "assigning to function table is illegal");
759 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100760 // TODO(bradnelson): Fix the parser and then un-comment this part
761 // BinaryOperation* bin = expr->key()->AsBinaryOperation();
Ben Murdochc5610432016-08-08 18:44:38 +0100762 // if (bin == nullptr || bin->op() != Token::BIT_AND) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100763 // FAIL(expr->key(), "expected & in call");
764 // }
765 // RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned,
766 // "array index expected to be integer"));
767 // Literal* right = bin->right()->AsLiteral();
Ben Murdochc5610432016-08-08 18:44:38 +0100768 // if (right == nullptr || right->raw_value()->ContainsDot()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100769 // FAIL(right, "call mask must be integer");
770 // }
771 // RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
772 // "call mask expected to be integer"));
773 // if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) {
774 // FAIL(right, "call mask must match function table");
775 // }
776 // bin->set_bounds(Bounds(cache_.kAsmSigned));
777 RECURSE(VisitWithExpectation(expr->key(), cache_.kAsmSigned,
778 "must be integer"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000779 IntersectResult(expr, type);
780 } else {
781 Literal* literal = expr->key()->AsLiteral();
782 if (literal) {
783 RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned,
784 "array index expected to be integer"));
785 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000786 int expected_shift = ElementShiftSize(type);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100787 if (expected_shift == 0) {
788 RECURSE(Visit(expr->key()));
789 } else {
790 BinaryOperation* bin = expr->key()->AsBinaryOperation();
Ben Murdochc5610432016-08-08 18:44:38 +0100791 if (bin == nullptr || bin->op() != Token::SAR) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100792 FAIL(expr->key(), "expected >> in heap access");
793 }
794 RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned,
795 "array index expected to be integer"));
796 Literal* right = bin->right()->AsLiteral();
Ben Murdochc5610432016-08-08 18:44:38 +0100797 if (right == nullptr || right->raw_value()->ContainsDot()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100798 FAIL(bin->right(), "heap access shift must be integer");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100799 }
800 RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
801 "array shift expected to be integer"));
802 int n = static_cast<int>(right->raw_value()->AsNumber());
803 if (expected_shift < 0 || n != expected_shift) {
804 FAIL(right, "heap access shift must match element size");
805 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000806 }
Ben Murdochc5610432016-08-08 18:44:38 +0100807 bounds_.set(expr->key(), Bounds(cache_.kAsmSigned));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000808 }
809 Type* result_type;
810 if (type->Is(cache_.kAsmIntArrayElement)) {
811 result_type = cache_.kAsmIntQ;
812 intish_ = kMaxUncombinedAdditiveSteps;
813 } else if (type->Is(cache_.kAsmFloat)) {
814 if (assigning) {
815 result_type = cache_.kAsmFloatDoubleQ;
816 } else {
817 result_type = cache_.kAsmFloatQ;
818 }
819 intish_ = 0;
820 } else if (type->Is(cache_.kAsmDouble)) {
821 if (assigning) {
822 result_type = cache_.kAsmFloatDoubleQ;
823 if (intish_ != 0) {
824 FAIL(expr, "Assignment of floatish to Float64Array");
825 }
826 } else {
827 result_type = cache_.kAsmDoubleQ;
828 }
829 intish_ = 0;
830 } else {
831 UNREACHABLE();
832 }
833 if (assigning) {
834 if (!assignment_type->Is(result_type)) {
835 FAIL(expr, "illegal type in assignment");
836 }
837 } else {
838 IntersectResult(expr, expected_type_);
839 IntersectResult(expr, result_type);
840 }
841 }
842}
843
844
845bool AsmTyper::IsStdlibObject(Expression* expr) {
846 VariableProxy* proxy = expr->AsVariableProxy();
Ben Murdochc5610432016-08-08 18:44:38 +0100847 if (proxy == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000848 return false;
849 }
850 Variable* var = proxy->var();
Ben Murdochc5610432016-08-08 18:44:38 +0100851 VariableInfo* info = GetVariableInfo(var);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852 if (info) {
853 if (info->standard_member == kStdlib) return true;
854 }
855 if (var->location() != VariableLocation::PARAMETER || var->index() != 0) {
856 return false;
857 }
Ben Murdochc5610432016-08-08 18:44:38 +0100858 info = MakeVariableInfo(var);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000859 info->type = Type::Object();
860 info->standard_member = kStdlib;
861 return true;
862}
863
864
865Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr,
866 const char* name) {
867 Property* property = expr->AsProperty();
Ben Murdochc5610432016-08-08 18:44:38 +0100868 if (property == nullptr) {
869 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870 }
871 Literal* key = property->key()->AsLiteral();
Ben Murdochc5610432016-08-08 18:44:38 +0100872 if (key == nullptr || !key->IsPropertyName() ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) {
Ben Murdochc5610432016-08-08 18:44:38 +0100874 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000875 }
876 return property->obj();
877}
878
879
880bool AsmTyper::IsMathObject(Expression* expr) {
881 Expression* obj = GetReceiverOfPropertyAccess(expr, "Math");
882 return obj && IsStdlibObject(obj);
883}
884
885
886bool AsmTyper::IsSIMDObject(Expression* expr) {
887 Expression* obj = GetReceiverOfPropertyAccess(expr, "SIMD");
888 return obj && IsStdlibObject(obj);
889}
890
891
892bool AsmTyper::IsSIMDTypeObject(Expression* expr, const char* name) {
893 Expression* obj = GetReceiverOfPropertyAccess(expr, name);
894 return obj && IsSIMDObject(obj);
895}
896
897
898void AsmTyper::VisitProperty(Property* expr) {
899 if (IsMathObject(expr->obj())) {
900 VisitLibraryAccess(&stdlib_math_types_, expr);
901 return;
902 }
903#define V(NAME, Name, name, lane_count, lane_type) \
904 if (IsSIMDTypeObject(expr->obj(), #Name)) { \
905 VisitLibraryAccess(&stdlib_simd_##name##_types_, expr); \
906 return; \
907 } \
908 if (IsSIMDTypeObject(expr, #Name)) { \
909 VariableInfo* info = stdlib_simd_##name##_constructor_type_; \
910 SetResult(expr, info->type); \
911 property_info_ = info; \
912 return; \
913 }
914 SIMD128_TYPES(V)
915#undef V
916 if (IsStdlibObject(expr->obj())) {
917 VisitLibraryAccess(&stdlib_types_, expr);
918 return;
919 }
920
Ben Murdochc5610432016-08-08 18:44:38 +0100921 property_info_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000922
923 // Only recurse at this point so that we avoid needing
924 // stdlib.Math to have a real type.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100925 RECURSE(
926 VisitWithExpectation(expr->obj(), Type::Any(), "bad property object"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000927
928 // For heap view or function table access.
929 if (computed_type_->IsArray()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100930 VisitHeapAccess(expr, false, nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 return;
932 }
933
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000934 VariableProxy* proxy = expr->obj()->AsVariableProxy();
Ben Murdochc5610432016-08-08 18:44:38 +0100935 if (proxy != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000936 Variable* var = proxy->var();
937 if (var->location() == VariableLocation::PARAMETER && var->index() == 1) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100938 // foreign.x - Function represent as () -> Any
939 if (Type::Any()->Is(expected_type_)) {
940 SetResult(expr, Type::Function(Type::Any(), zone()));
941 } else {
942 SetResult(expr, expected_type_);
943 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000944 return;
945 }
946 }
947
948 FAIL(expr, "invalid property access");
949}
950
Ben Murdochda12d292016-06-02 14:46:10 +0100951void AsmTyper::CheckPolymorphicStdlibArguments(
952 enum StandardMember standard_member, ZoneList<Expression*>* args) {
953 if (args->length() == 0) {
954 return;
955 }
956 // Handle polymorphic stdlib functions specially.
957 Expression* arg0 = args->at(0);
Ben Murdochc5610432016-08-08 18:44:38 +0100958 Type* arg0_type = bounds_.get(arg0).upper;
Ben Murdochda12d292016-06-02 14:46:10 +0100959 switch (standard_member) {
960 case kMathFround: {
961 if (!arg0_type->Is(cache_.kAsmFloat) &&
962 !arg0_type->Is(cache_.kAsmDouble) &&
963 !arg0_type->Is(cache_.kAsmSigned) &&
964 !arg0_type->Is(cache_.kAsmUnsigned)) {
965 FAIL(arg0, "illegal function argument type");
966 }
967 break;
968 }
969 case kMathCeil:
970 case kMathFloor:
971 case kMathSqrt: {
972 if (!arg0_type->Is(cache_.kAsmFloat) &&
973 !arg0_type->Is(cache_.kAsmDouble)) {
974 FAIL(arg0, "illegal function argument type");
975 }
976 break;
977 }
978 case kMathAbs:
979 case kMathMin:
980 case kMathMax: {
981 if (!arg0_type->Is(cache_.kAsmFloat) &&
982 !arg0_type->Is(cache_.kAsmDouble) &&
983 !arg0_type->Is(cache_.kAsmSigned)) {
984 FAIL(arg0, "illegal function argument type");
985 }
986 if (args->length() > 1) {
Ben Murdochc5610432016-08-08 18:44:38 +0100987 Type* other = Type::Intersect(bounds_.get(args->at(0)).upper,
988 bounds_.get(args->at(1)).upper, zone());
Ben Murdochda12d292016-06-02 14:46:10 +0100989 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) &&
990 !other->Is(cache_.kAsmSigned)) {
991 FAIL(arg0, "function arguments types don't match");
992 }
993 }
994 break;
995 }
996 default: { break; }
997 }
998}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999
1000void AsmTyper::VisitCall(Call* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001001 Type* expected_type = expected_type_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001002 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
1003 "callee expected to be any"));
1004 StandardMember standard_member = kNone;
1005 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1006 if (proxy) {
1007 standard_member = VariableAsStandardMember(proxy->var());
1008 }
Ben Murdochc5610432016-08-08 18:44:38 +01001009 if (!in_function_ && (proxy == nullptr || standard_member != kMathFround)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001010 FAIL(expr, "calls forbidden outside function bodies");
1011 }
Ben Murdochc5610432016-08-08 18:44:38 +01001012 if (proxy == nullptr && !expr->expression()->IsProperty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 FAIL(expr, "calls must be to bound variables or function tables");
1014 }
1015 if (computed_type_->IsFunction()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001016 FunctionType* fun_type = computed_type_->AsFunction();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001017 Type* result_type = fun_type->Result();
1018 ZoneList<Expression*>* args = expr->arguments();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001019 if (Type::Any()->Is(result_type)) {
1020 // For foreign calls.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001021 for (int i = 0; i < args->length(); ++i) {
1022 Expression* arg = args->at(i);
1023 RECURSE(VisitWithExpectation(
1024 arg, Type::Any(), "foreign call argument expected to be any"));
1025 // Checking for asm extern types explicitly, as the type system
1026 // doesn't correctly check their inheritance relationship.
1027 if (!computed_type_->Is(cache_.kAsmSigned) &&
1028 !computed_type_->Is(cache_.kAsmFixnum) &&
1029 !computed_type_->Is(cache_.kAsmDouble)) {
1030 FAIL(arg,
1031 "foreign call argument expected to be int, double, or fixnum");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001032 }
1033 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001034 intish_ = 0;
Ben Murdochc5610432016-08-08 18:44:38 +01001035 bounds_.set(expr->expression(),
1036 Bounds(Type::Function(Type::Any(), zone())));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001037 IntersectResult(expr, expected_type);
1038 } else {
1039 if (fun_type->Arity() != args->length()) {
1040 FAIL(expr, "call with wrong arity");
1041 }
1042 for (int i = 0; i < args->length(); ++i) {
1043 Expression* arg = args->at(i);
1044 RECURSE(VisitWithExpectation(
1045 arg, fun_type->Parameter(i),
1046 "call argument expected to match callee parameter"));
1047 if (standard_member != kNone && standard_member != kMathFround &&
1048 i == 0) {
1049 result_type = computed_type_;
1050 }
1051 }
Ben Murdochda12d292016-06-02 14:46:10 +01001052 RECURSE(CheckPolymorphicStdlibArguments(standard_member, args));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001053 intish_ = 0;
1054 IntersectResult(expr, result_type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001056 } else {
1057 FAIL(expr, "invalid callee");
1058 }
1059}
1060
1061
1062void AsmTyper::VisitCallNew(CallNew* expr) {
1063 if (in_function_) {
1064 FAIL(expr, "new not allowed in module function");
1065 }
1066 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
1067 "expected stdlib function"));
1068 if (computed_type_->IsFunction()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001069 FunctionType* fun_type = computed_type_->AsFunction();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001070 ZoneList<Expression*>* args = expr->arguments();
1071 if (fun_type->Arity() != args->length())
1072 FAIL(expr, "call with wrong arity");
1073 for (int i = 0; i < args->length(); ++i) {
1074 Expression* arg = args->at(i);
1075 RECURSE(VisitWithExpectation(
1076 arg, fun_type->Parameter(i),
1077 "constructor argument expected to match callee parameter"));
1078 }
1079 IntersectResult(expr, fun_type->Result());
1080 return;
1081 }
1082
1083 FAIL(expr, "ill-typed new operator");
1084}
1085
1086
1087void AsmTyper::VisitCallRuntime(CallRuntime* expr) {
Ben Murdochc5610432016-08-08 18:44:38 +01001088 FAIL(expr, "runtime call not allowed");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001089}
1090
1091
1092void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001093 if (!in_function_) {
1094 FAIL(expr, "unary operator inside module body");
1095 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001096 switch (expr->op()) {
1097 case Token::NOT: // Used to encode != and !==
1098 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt,
1099 "operand expected to be integer"));
1100 IntersectResult(expr, cache_.kAsmSigned);
1101 return;
1102 case Token::DELETE:
1103 FAIL(expr, "delete operator encountered");
1104 case Token::VOID:
1105 FAIL(expr, "void operator encountered");
1106 case Token::TYPEOF:
1107 FAIL(expr, "typeof operator encountered");
1108 default:
1109 UNREACHABLE();
1110 }
1111}
1112
1113
1114void AsmTyper::VisitCountOperation(CountOperation* expr) {
1115 FAIL(expr, "increment or decrement operator encountered");
1116}
1117
1118
1119void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
1120 Type* left_expected,
1121 Type* right_expected,
1122 Type* result_type, bool conversion) {
1123 RECURSE(VisitWithExpectation(expr->left(), Type::Number(),
1124 "left bitwise operand expected to be a number"));
Ben Murdochda12d292016-06-02 14:46:10 +01001125 int32_t left_intish = intish_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001126 Type* left_type = computed_type_;
1127 if (!left_type->Is(left_expected)) {
1128 FAIL(expr->left(), "left bitwise operand expected to be an integer");
1129 }
1130 if (left_intish > kMaxUncombinedAdditiveSteps) {
1131 FAIL(expr->left(), "too many consecutive additive ops");
1132 }
1133
1134 RECURSE(
1135 VisitWithExpectation(expr->right(), Type::Number(),
1136 "right bitwise operand expected to be a number"));
Ben Murdochda12d292016-06-02 14:46:10 +01001137 int32_t right_intish = intish_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001138 Type* right_type = computed_type_;
1139 if (!right_type->Is(right_expected)) {
1140 FAIL(expr->right(), "right bitwise operand expected to be an integer");
1141 }
1142 if (right_intish > kMaxUncombinedAdditiveSteps) {
1143 FAIL(expr->right(), "too many consecutive additive ops");
1144 }
1145
1146 intish_ = 0;
1147
1148 if (left_type->Is(cache_.kAsmFixnum) && right_type->Is(cache_.kAsmInt)) {
1149 left_type = right_type;
1150 }
1151 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) {
1152 right_type = left_type;
1153 }
1154 if (!conversion) {
Ben Murdochda12d292016-06-02 14:46:10 +01001155 if (!left_type->Is(cache_.kAsmIntQ) || !right_type->Is(cache_.kAsmIntQ)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001156 FAIL(expr, "ill-typed bitwise operation");
1157 }
1158 }
1159 IntersectResult(expr, result_type);
1160}
1161
1162
1163void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001164 if (!in_function_) {
1165 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) {
1166 FAIL(expr, "illegal binary operator inside module body");
1167 }
1168 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) ||
1169 !expr->right()->IsLiteral()) {
1170 FAIL(expr, "illegal computation inside module body");
1171 }
1172 DCHECK(expr->right()->AsLiteral() != nullptr);
1173 const AstValue* right_value = expr->right()->AsLiteral()->raw_value();
1174 if (expr->op() == Token::BIT_OR) {
1175 if (right_value->AsNumber() != 0.0 || right_value->ContainsDot()) {
1176 FAIL(expr, "illegal integer annotation value");
1177 }
1178 }
1179 if (expr->op() == Token::MUL) {
1180 if (right_value->AsNumber() != 1.0 && right_value->ContainsDot()) {
1181 FAIL(expr, "illegal double annotation value");
1182 }
1183 }
1184 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185 switch (expr->op()) {
1186 case Token::COMMA: {
1187 RECURSE(VisitWithExpectation(expr->left(), Type::Any(),
1188 "left comma operand expected to be any"));
1189 RECURSE(VisitWithExpectation(expr->right(), Type::Any(),
1190 "right comma operand expected to be any"));
1191 IntersectResult(expr, computed_type_);
1192 return;
1193 }
1194 case Token::OR:
1195 case Token::AND:
1196 FAIL(expr, "illegal logical operator");
1197 case Token::BIT_OR: {
1198 // BIT_OR allows Any since it is used as a type coercion.
Ben Murdochda12d292016-06-02 14:46:10 +01001199 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ,
1200 cache_.kAsmSigned, true));
1201 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR &&
Ben Murdochc5610432016-08-08 18:44:38 +01001202 Type::Number()->Is(bounds_.get(expr->left()).upper)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001203 // Force the return types of foreign functions.
Ben Murdochc5610432016-08-08 18:44:38 +01001204 bounds_.set(expr->left(), Bounds(cache_.kAsmSigned));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001205 }
Ben Murdochc5610432016-08-08 18:44:38 +01001206 if (in_function_ &&
1207 !bounds_.get(expr->left()).upper->Is(cache_.kAsmIntQ)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001208 FAIL(expr->left(), "intish required");
1209 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001210 return;
1211 }
1212 case Token::BIT_XOR: {
1213 // Handle booleans specially to handle de-sugared !
1214 Literal* left = expr->left()->AsLiteral();
1215 if (left && left->value()->IsBoolean()) {
1216 if (left->ToBooleanIsTrue()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001217 bounds_.set(left, Bounds(cache_.kSingletonOne));
Ben Murdochda12d292016-06-02 14:46:10 +01001218 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmIntQ,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001219 "not operator expects an integer"));
1220 IntersectResult(expr, cache_.kAsmSigned);
1221 return;
1222 } else {
1223 FAIL(left, "unexpected false");
1224 }
1225 }
Ben Murdochda12d292016-06-02 14:46:10 +01001226 // BIT_XOR allows Any since it is used as a type coercion (via ~~).
1227 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ,
1228 cache_.kAsmSigned, true));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001229 return;
1230 }
1231 case Token::SHR: {
Ben Murdochda12d292016-06-02 14:46:10 +01001232 RECURSE(VisitIntegerBitwiseOperator(
1233 expr, cache_.kAsmIntQ, cache_.kAsmIntQ, cache_.kAsmUnsigned, false));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 return;
1235 }
1236 case Token::SHL:
1237 case Token::SAR:
1238 case Token::BIT_AND: {
Ben Murdochda12d292016-06-02 14:46:10 +01001239 RECURSE(VisitIntegerBitwiseOperator(
1240 expr, cache_.kAsmIntQ, cache_.kAsmIntQ, cache_.kAsmSigned, false));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001241 return;
1242 }
1243 case Token::ADD:
1244 case Token::SUB:
1245 case Token::MUL:
1246 case Token::DIV:
1247 case Token::MOD: {
1248 RECURSE(VisitWithExpectation(
1249 expr->left(), Type::Number(),
1250 "left arithmetic operand expected to be number"));
1251 Type* left_type = computed_type_;
Ben Murdochda12d292016-06-02 14:46:10 +01001252 int32_t left_intish = intish_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001253 RECURSE(VisitWithExpectation(
1254 expr->right(), Type::Number(),
1255 "right arithmetic operand expected to be number"));
1256 Type* right_type = computed_type_;
Ben Murdochda12d292016-06-02 14:46:10 +01001257 int32_t right_intish = intish_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001258 Type* type = Type::Union(left_type, right_type, zone());
1259 if (type->Is(cache_.kAsmInt)) {
1260 if (expr->op() == Token::MUL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001261 int32_t i;
Ben Murdochda12d292016-06-02 14:46:10 +01001262 Literal* left = expr->left()->AsLiteral();
1263 Literal* right = expr->right()->AsLiteral();
1264 if (left != nullptr && left->value()->IsNumber() &&
1265 left->value()->ToInt32(&i)) {
1266 if (right_intish != 0) {
1267 FAIL(expr, "intish not allowed in multiply");
1268 }
1269 } else if (right != nullptr && right->value()->IsNumber() &&
1270 right->value()->ToInt32(&i)) {
1271 if (left_intish != 0) {
1272 FAIL(expr, "intish not allowed in multiply");
1273 }
1274 } else {
1275 FAIL(expr, "multiply must be by an integer literal");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276 }
1277 i = abs(i);
Ben Murdochda12d292016-06-02 14:46:10 +01001278 if (i >= (1 << 20)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001279 FAIL(expr, "multiply must be by value in -2^20 < n < 2^20");
1280 }
1281 intish_ = i;
1282 IntersectResult(expr, cache_.kAsmInt);
1283 return;
1284 } else {
1285 intish_ = left_intish + right_intish + 1;
1286 if (expr->op() == Token::ADD || expr->op() == Token::SUB) {
1287 if (intish_ > kMaxUncombinedAdditiveSteps) {
1288 FAIL(expr, "too many consecutive additive ops");
1289 }
1290 } else {
1291 if (intish_ > kMaxUncombinedMultiplicativeSteps) {
1292 FAIL(expr, "too many consecutive multiplicative ops");
1293 }
1294 }
1295 IntersectResult(expr, cache_.kAsmInt);
1296 return;
1297 }
1298 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() &&
Ben Murdochda12d292016-06-02 14:46:10 +01001299 right_type->Is(cache_.kAsmDouble) &&
1300 expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
1301 expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001302 // For unary +, expressed as x * 1.0
Ben Murdochda12d292016-06-02 14:46:10 +01001303 if (expr->left()->IsCall() &&
Ben Murdochc5610432016-08-08 18:44:38 +01001304 Type::Number()->Is(bounds_.get(expr->left()).upper)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001305 // Force the return types of foreign functions.
Ben Murdochc5610432016-08-08 18:44:38 +01001306 bounds_.set(expr->left(), Bounds(cache_.kAsmDouble));
1307 left_type = bounds_.get(expr->left()).upper;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001308 }
Ben Murdochda12d292016-06-02 14:46:10 +01001309 if (!(expr->left()->IsProperty() &&
Ben Murdochc5610432016-08-08 18:44:38 +01001310 Type::Number()->Is(bounds_.get(expr->left()).upper))) {
Ben Murdochda12d292016-06-02 14:46:10 +01001311 if (!left_type->Is(cache_.kAsmSigned) &&
1312 !left_type->Is(cache_.kAsmUnsigned) &&
1313 !left_type->Is(cache_.kAsmFixnum) &&
1314 !left_type->Is(cache_.kAsmFloatQ) &&
1315 !left_type->Is(cache_.kAsmDoubleQ)) {
1316 FAIL(
1317 expr->left(),
1318 "unary + only allowed on signed, unsigned, float?, or double?");
1319 }
1320 }
1321 IntersectResult(expr, cache_.kAsmDouble);
1322 return;
1323 } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmDouble) &&
1324 expr->right()->IsLiteral() &&
1325 !expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
1326 expr->right()->AsLiteral()->raw_value()->AsNumber() == -1.0) {
1327 // For unary -, expressed as x * -1
Ben Murdochc5610432016-08-08 18:44:38 +01001328 bounds_.set(expr->right(), Bounds(cache_.kAsmDouble));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001329 IntersectResult(expr, cache_.kAsmDouble);
1330 return;
1331 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) {
1332 if (left_intish != 0 || right_intish != 0) {
1333 FAIL(expr, "float operation before required fround");
1334 }
1335 IntersectResult(expr, cache_.kAsmFloat);
1336 intish_ = 1;
1337 return;
1338 } else if (type->Is(cache_.kAsmDouble)) {
1339 IntersectResult(expr, cache_.kAsmDouble);
1340 return;
1341 } else {
1342 FAIL(expr, "ill-typed arithmetic operation");
1343 }
1344 }
1345 default:
1346 UNREACHABLE();
1347 }
1348}
1349
1350
1351void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001352 if (!in_function_) {
1353 FAIL(expr, "comparison inside module body");
1354 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001355 Token::Value op = expr->op();
1356 if (op != Token::EQ && op != Token::NE && op != Token::LT &&
1357 op != Token::LTE && op != Token::GT && op != Token::GTE) {
1358 FAIL(expr, "illegal comparison operator");
1359 }
1360
1361 RECURSE(
1362 VisitWithExpectation(expr->left(), Type::Number(),
1363 "left comparison operand expected to be number"));
1364 Type* left_type = computed_type_;
1365 if (!left_type->Is(cache_.kAsmComparable)) {
1366 FAIL(expr->left(), "bad type on left side of comparison");
1367 }
1368
1369 RECURSE(
1370 VisitWithExpectation(expr->right(), Type::Number(),
1371 "right comparison operand expected to be number"));
1372 Type* right_type = computed_type_;
1373 if (!right_type->Is(cache_.kAsmComparable)) {
1374 FAIL(expr->right(), "bad type on right side of comparison");
1375 }
1376
1377 if (!left_type->Is(right_type) && !right_type->Is(left_type)) {
1378 FAIL(expr, "left and right side of comparison must match");
1379 }
1380
1381 IntersectResult(expr, cache_.kAsmSigned);
1382}
1383
1384
1385void AsmTyper::VisitThisFunction(ThisFunction* expr) {
1386 FAIL(expr, "this function not allowed");
1387}
1388
1389
1390void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
1391 for (int i = 0; i < decls->length(); ++i) {
1392 Declaration* decl = decls->at(i);
1393 RECURSE(Visit(decl));
1394 }
1395}
1396
1397
1398void AsmTyper::VisitImportDeclaration(ImportDeclaration* decl) {
1399 FAIL(decl, "import declaration encountered");
1400}
1401
1402
1403void AsmTyper::VisitExportDeclaration(ExportDeclaration* decl) {
1404 FAIL(decl, "export declaration encountered");
1405}
1406
1407
1408void AsmTyper::VisitClassLiteral(ClassLiteral* expr) {
1409 FAIL(expr, "class literal not allowed");
1410}
1411
1412
1413void AsmTyper::VisitSpread(Spread* expr) { FAIL(expr, "spread not allowed"); }
1414
1415
1416void AsmTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) {
1417 FAIL(expr, "super property reference not allowed");
1418}
1419
1420
1421void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) {
1422 FAIL(expr, "call reference not allowed");
1423}
1424
1425
1426void AsmTyper::InitializeStdlibSIMD() {
1427#define V(NAME, Name, name, lane_count, lane_type) \
1428 { \
1429 Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(), \
1430 lane_count, zone()); \
1431 for (int i = 0; i < lane_count; ++i) { \
1432 type->AsFunction()->InitParameter(i, Type::Number()); \
1433 } \
1434 stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \
1435 stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \
1436 }
1437 SIMD128_TYPES(V)
1438#undef V
1439}
1440
1441
1442void AsmTyper::InitializeStdlib() {
1443 if (allow_simd_) {
1444 InitializeStdlibSIMD();
1445 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001446 Type* number_type = Type::Number();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001447 Type* double_type = cache_.kAsmDouble;
1448 Type* double_fn1_type = Type::Function(double_type, double_type, zone());
1449 Type* double_fn2_type =
1450 Type::Function(double_type, double_type, double_type, zone());
1451
1452 Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone());
1453 Type* imul_type =
1454 Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone());
1455 // TODO(bradnelson): currently only approximating the proper intersection type
1456 // (which we cannot currently represent).
1457 Type* number_fn1_type = Type::Function(number_type, number_type, zone());
1458 Type* number_fn2_type =
1459 Type::Function(number_type, number_type, number_type, zone());
1460
1461 struct Assignment {
1462 const char* name;
1463 StandardMember standard_member;
1464 Type* type;
1465 };
1466
1467 const Assignment math[] = {{"PI", kMathPI, double_type},
1468 {"E", kMathE, double_type},
1469 {"LN2", kMathLN2, double_type},
1470 {"LN10", kMathLN10, double_type},
1471 {"LOG2E", kMathLOG2E, double_type},
1472 {"LOG10E", kMathLOG10E, double_type},
1473 {"SQRT2", kMathSQRT2, double_type},
1474 {"SQRT1_2", kMathSQRT1_2, double_type},
1475 {"imul", kMathImul, imul_type},
1476 {"abs", kMathAbs, number_fn1_type},
1477 {"ceil", kMathCeil, number_fn1_type},
1478 {"floor", kMathFloor, number_fn1_type},
1479 {"fround", kMathFround, fround_type},
1480 {"pow", kMathPow, double_fn2_type},
1481 {"exp", kMathExp, double_fn1_type},
1482 {"log", kMathLog, double_fn1_type},
1483 {"min", kMathMin, number_fn2_type},
1484 {"max", kMathMax, number_fn2_type},
1485 {"sqrt", kMathSqrt, number_fn1_type},
1486 {"cos", kMathCos, double_fn1_type},
1487 {"sin", kMathSin, double_fn1_type},
1488 {"tan", kMathTan, double_fn1_type},
1489 {"acos", kMathAcos, double_fn1_type},
1490 {"asin", kMathAsin, double_fn1_type},
1491 {"atan", kMathAtan, double_fn1_type},
1492 {"atan2", kMathAtan2, double_fn2_type}};
1493 for (unsigned i = 0; i < arraysize(math); ++i) {
1494 stdlib_math_types_[math[i].name] = new (zone()) VariableInfo(math[i].type);
1495 stdlib_math_types_[math[i].name]->standard_member = math[i].standard_member;
1496 }
1497 stdlib_math_types_["fround"]->is_check_function = true;
1498
1499 stdlib_types_["Infinity"] = new (zone()) VariableInfo(double_type);
1500 stdlib_types_["Infinity"]->standard_member = kInfinity;
1501 stdlib_types_["NaN"] = new (zone()) VariableInfo(double_type);
1502 stdlib_types_["NaN"]->standard_member = kNaN;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001503 Type* buffer_type = Type::Any();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001504#define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
1505 stdlib_types_[#TypeName "Array"] = new (zone()) VariableInfo( \
1506 Type::Function(cache_.k##TypeName##Array, buffer_type, zone()));
1507 TYPED_ARRAYS(TYPED_ARRAY)
1508#undef TYPED_ARRAY
1509
1510#define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
1511 stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \
1512 Type::Function(cache_.k##TypeName##Array, buffer_type, zone()));
1513 TYPED_ARRAYS(TYPED_ARRAY)
1514#undef TYPED_ARRAY
1515}
1516
1517
1518void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) {
1519 Literal* key = expr->key()->AsLiteral();
Ben Murdochc5610432016-08-08 18:44:38 +01001520 if (key == nullptr || !key->IsPropertyName())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001521 FAIL(expr, "invalid key used on stdlib member");
1522 Handle<String> name = key->AsPropertyName();
1523 VariableInfo* info = LibType(map, name);
Ben Murdochc5610432016-08-08 18:44:38 +01001524 if (info == nullptr || info->type == nullptr)
1525 FAIL(expr, "unknown stdlib function");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001526 SetResult(expr, info->type);
1527 property_info_ = info;
1528}
1529
1530
1531AsmTyper::VariableInfo* AsmTyper::LibType(ObjectTypeMap* map,
1532 Handle<String> name) {
1533 base::SmartArrayPointer<char> aname = name->ToCString();
1534 ObjectTypeMap::iterator i = map->find(std::string(aname.get()));
1535 if (i == map->end()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001536 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001537 }
1538 return i->second;
1539}
1540
1541
1542void AsmTyper::SetType(Variable* variable, Type* type) {
Ben Murdochc5610432016-08-08 18:44:38 +01001543 VariableInfo* info = MakeVariableInfo(variable);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001544 info->type = type;
1545}
1546
1547
1548Type* AsmTyper::GetType(Variable* variable) {
Ben Murdochc5610432016-08-08 18:44:38 +01001549 VariableInfo* info = GetVariableInfo(variable);
1550 if (!info) return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551 return info->type;
1552}
1553
Ben Murdochc5610432016-08-08 18:44:38 +01001554AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable) {
1555 ZoneHashMap* map =
1556 in_function_ ? &local_variable_type_ : &global_variable_type_;
1557 ZoneHashMap::Entry* entry =
1558 map->Lookup(variable, ComputePointerHash(variable));
1559 if (!entry && in_function_) {
1560 entry =
1561 global_variable_type_.Lookup(variable, ComputePointerHash(variable));
1562 }
1563 return entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr;
1564}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001565
Ben Murdochc5610432016-08-08 18:44:38 +01001566AsmTyper::VariableInfo* AsmTyper::MakeVariableInfo(Variable* variable) {
1567 ZoneHashMap* map =
1568 in_function_ ? &local_variable_type_ : &global_variable_type_;
1569 ZoneHashMap::Entry* entry = map->LookupOrInsert(
1570 variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone()));
1571 if (!entry->value) entry->value = new (zone()) VariableInfo;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001572 return reinterpret_cast<VariableInfo*>(entry->value);
1573}
1574
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001575void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) {
Ben Murdochc5610432016-08-08 18:44:38 +01001576 VariableInfo* dest = MakeVariableInfo(variable);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001577 dest->type = info->type;
1578 dest->is_check_function = info->is_check_function;
1579 dest->is_constructor_function = info->is_constructor_function;
1580 dest->standard_member = info->standard_member;
1581}
1582
1583
1584AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(
1585 Variable* variable) {
Ben Murdochc5610432016-08-08 18:44:38 +01001586 VariableInfo* info = GetVariableInfo(variable);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001587 if (!info) return kNone;
1588 return info->standard_member;
1589}
1590
1591
1592void AsmTyper::SetResult(Expression* expr, Type* type) {
1593 computed_type_ = type;
Ben Murdochc5610432016-08-08 18:44:38 +01001594 bounds_.set(expr, Bounds(computed_type_));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001595}
1596
1597
1598void AsmTyper::IntersectResult(Expression* expr, Type* type) {
1599 computed_type_ = type;
1600 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
Ben Murdochc5610432016-08-08 18:44:38 +01001601 bounds_.set(expr, Bounds(bounded_type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001602}
1603
1604
1605void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type,
1606 const char* msg) {
1607 Type* save = expected_type_;
1608 expected_type_ = expected_type;
1609 RECURSE(Visit(expr));
1610 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001611 if (bounded_type->Is(Type::None())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001612#ifdef DEBUG
1613 PrintF("Computed type: ");
1614 computed_type_->Print();
1615 PrintF("Expected type: ");
1616 expected_type_->Print();
1617#endif
1618 FAIL(expr, msg);
1619 }
1620 expected_type_ = save;
1621}
1622
1623
Ben Murdoch097c5b22016-05-18 11:27:45 +01001624void AsmTyper::VisitRewritableExpression(RewritableExpression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001625 RECURSE(Visit(expr->expression()));
1626}
1627
1628
1629} // namespace internal
1630} // namespace v8