blob: 2390e7e7b12a824229e8d68768896c35791836d4 [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
Ben Murdoch61f157c2016-09-16 13:49:30 +010056 global_variable_type_(base::HashMap::PointersMatch,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000057 ZoneHashMap::kDefaultHashMapCapacity,
58 ZoneAllocationPolicy(zone)),
Ben Murdoch61f157c2016-09-16 13:49:30 +010059 local_variable_type_(base::HashMap::PointersMatch,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 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 Murdoch61f157c2016-09-16 13:49:30 +0100169 if (GetVariableInfo(var)) {
170 // Detect previously-seen functions.
171 FAIL(decl->fun(), "function repeated in module");
172 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100173 SetType(var, Type::Function());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174}
175
176
177void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) {
178 // Extract result type.
179 ZoneList<Statement*>* body = fun->body();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100180 Type* result_type = Type::Undefined();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 if (body->length() > 0) {
182 ReturnStatement* stmt = body->last()->AsReturnStatement();
Ben Murdochc5610432016-08-08 18:44:38 +0100183 if (stmt != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 Literal* literal = stmt->expression()->AsLiteral();
185 Type* old_expected = expected_type_;
186 expected_type_ = Type::Any();
187 if (literal) {
188 RECURSE(VisitLiteral(literal, true));
189 } else {
Ben Murdochc5610432016-08-08 18:44:38 +0100190 RECURSE(VisitExpressionAnnotation(stmt->expression(), nullptr, true));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 }
192 expected_type_ = old_expected;
193 result_type = computed_type_;
194 }
195 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100196 Type* type =
197 Type::Function(result_type, Type::Any(), fun->parameter_count(), zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198
199 // Extract parameter types.
200 bool good = true;
201 for (int i = 0; i < fun->parameter_count(); ++i) {
202 good = false;
203 if (i >= body->length()) break;
204 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement();
Ben Murdochc5610432016-08-08 18:44:38 +0100205 if (stmt == nullptr) break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 Assignment* expr = stmt->expression()->AsAssignment();
Ben Murdochc5610432016-08-08 18:44:38 +0100207 if (expr == nullptr || expr->is_compound()) break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 VariableProxy* proxy = expr->target()->AsVariableProxy();
Ben Murdochc5610432016-08-08 18:44:38 +0100209 if (proxy == nullptr) break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 Variable* var = proxy->var();
211 if (var->location() != VariableLocation::PARAMETER || var->index() != i)
212 break;
213 RECURSE(VisitExpressionAnnotation(expr->value(), var, false));
Ben Murdochc5610432016-08-08 18:44:38 +0100214 if (property_info_ != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215 SetVariableInfo(var, property_info_);
Ben Murdochc5610432016-08-08 18:44:38 +0100216 property_info_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217 }
218 SetType(var, computed_type_);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100219 type->AsFunction()->InitParameter(i, computed_type_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 good = true;
221 }
222 if (!good) FAIL(fun, "missing parameter type annotations");
223
224 SetResult(fun, type);
225}
226
227
228void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var,
229 bool is_return) {
230 // Normal +x or x|0 annotations.
231 BinaryOperation* bin = expr->AsBinaryOperation();
Ben Murdochc5610432016-08-08 18:44:38 +0100232 if (bin != nullptr) {
233 if (var != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 VariableProxy* proxy = bin->left()->AsVariableProxy();
Ben Murdochc5610432016-08-08 18:44:38 +0100235 if (proxy == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 FAIL(bin->left(), "expected variable for type annotation");
237 }
238 if (proxy->var() != var) {
239 FAIL(proxy, "annotation source doesn't match destination");
240 }
241 }
242 Literal* right = bin->right()->AsLiteral();
Ben Murdochc5610432016-08-08 18:44:38 +0100243 if (right != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 switch (bin->op()) {
245 case Token::MUL: // We encode +x as x*1.0
246 if (right->raw_value()->ContainsDot() &&
247 right->raw_value()->AsNumber() == 1.0) {
248 SetResult(expr, cache_.kAsmDouble);
249 return;
250 }
251 break;
252 case Token::BIT_OR:
253 if (!right->raw_value()->ContainsDot() &&
254 right->raw_value()->AsNumber() == 0.0) {
255 if (is_return) {
256 SetResult(expr, cache_.kAsmSigned);
257 } else {
258 SetResult(expr, cache_.kAsmInt);
259 }
260 return;
261 }
262 break;
263 default:
264 break;
265 }
266 }
267 FAIL(expr, "invalid type annotation on binary op");
268 }
269
270 // Numbers or the undefined literal (for empty returns).
271 if (expr->IsLiteral()) {
272 RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal"));
273 return;
274 }
275
276 Call* call = expr->AsCall();
Ben Murdochc5610432016-08-08 18:44:38 +0100277 if (call != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 VariableProxy* proxy = call->expression()->AsVariableProxy();
Ben Murdochc5610432016-08-08 18:44:38 +0100279 if (proxy != nullptr) {
280 VariableInfo* info = GetVariableInfo(proxy->var());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 if (!info ||
282 (!info->is_check_function && !info->is_constructor_function)) {
283 if (allow_simd_) {
284 FAIL(call->expression(),
285 "only fround/SIMD.checks allowed on expression annotations");
286 } else {
287 FAIL(call->expression(),
288 "only fround allowed on expression annotations");
289 }
290 }
291 Type* type = info->type;
292 DCHECK(type->IsFunction());
293 if (info->is_check_function) {
294 DCHECK(type->AsFunction()->Arity() == 1);
295 }
296 if (call->arguments()->length() != type->AsFunction()->Arity()) {
297 FAIL(call, "invalid argument count calling function");
298 }
299 SetResult(expr, type->AsFunction()->Result());
300 return;
301 }
302 }
303
304 FAIL(expr, "invalid type annotation");
305}
306
307
308void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) {
309 for (int i = 0; i < stmts->length(); ++i) {
310 Statement* stmt = stmts->at(i);
311 RECURSE(Visit(stmt));
312 }
313}
314
315
316void AsmTyper::VisitBlock(Block* stmt) {
317 RECURSE(VisitStatements(stmt->statements()));
318}
319
320
321void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
322 RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(),
323 "expression statement expected to be any"));
324}
325
326
327void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {}
328
329
330void AsmTyper::VisitSloppyBlockFunctionStatement(
331 SloppyBlockFunctionStatement* stmt) {
332 Visit(stmt->statement());
333}
334
335
336void AsmTyper::VisitEmptyParentheses(EmptyParentheses* expr) { UNREACHABLE(); }
337
338
339void AsmTyper::VisitIfStatement(IfStatement* stmt) {
340 if (!in_function_) {
341 FAIL(stmt, "if statement inside module body");
342 }
343 RECURSE(VisitWithExpectation(stmt->condition(), cache_.kAsmSigned,
344 "if condition expected to be integer"));
345 RECURSE(Visit(stmt->then_statement()));
346 RECURSE(Visit(stmt->else_statement()));
347}
348
349
350void AsmTyper::VisitContinueStatement(ContinueStatement* stmt) {
351 if (!in_function_) {
352 FAIL(stmt, "continue statement inside module body");
353 }
354}
355
356
357void AsmTyper::VisitBreakStatement(BreakStatement* stmt) {
358 if (!in_function_) {
359 FAIL(stmt, "continue statement inside module body");
360 }
361}
362
363
364void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) {
365 // Handle module return statement in VisitAsmModule.
366 if (!in_function_) {
367 return;
368 }
369 Literal* literal = stmt->expression()->AsLiteral();
370 if (literal) {
371 VisitLiteral(literal, true);
372 } else {
373 RECURSE(
374 VisitWithExpectation(stmt->expression(), Type::Any(),
375 "return expression expected to have return type"));
376 }
377 if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) {
378 FAIL(stmt->expression(), "return type does not match function signature");
379 }
380}
381
382
383void AsmTyper::VisitWithStatement(WithStatement* stmt) {
384 FAIL(stmt, "bad with statement");
385}
386
387
388void AsmTyper::VisitSwitchStatement(SwitchStatement* stmt) {
389 if (!in_function_) {
390 FAIL(stmt, "switch statement inside module body");
391 }
392 RECURSE(VisitWithExpectation(stmt->tag(), cache_.kAsmSigned,
393 "switch expression non-integer"));
394 ZoneList<CaseClause*>* clauses = stmt->cases();
395 ZoneSet<int32_t> cases(zone());
396 for (int i = 0; i < clauses->length(); ++i) {
397 CaseClause* clause = clauses->at(i);
398 if (clause->is_default()) {
399 if (i != clauses->length() - 1) {
400 FAIL(clause, "default case out of order");
401 }
402 } else {
403 Expression* label = clause->label();
404 RECURSE(VisitWithExpectation(label, cache_.kAsmSigned,
405 "case label non-integer"));
406 if (!label->IsLiteral()) FAIL(label, "non-literal case label");
407 Handle<Object> value = label->AsLiteral()->value();
408 int32_t value32;
409 if (!value->ToInt32(&value32)) FAIL(label, "illegal case label value");
410 if (cases.find(value32) != cases.end()) {
411 FAIL(label, "duplicate case value");
412 }
413 cases.insert(value32);
414 }
415 // TODO(bradnelson): Detect duplicates.
416 ZoneList<Statement*>* stmts = clause->statements();
417 RECURSE(VisitStatements(stmts));
418 }
419 if (cases.size() > 0) {
420 int64_t min_case = *cases.begin();
421 int64_t max_case = *cases.rbegin();
422 if (max_case - min_case > std::numeric_limits<int32_t>::max()) {
423 FAIL(stmt, "case range too large");
424 }
425 }
426}
427
428
429void AsmTyper::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }
430
431
432void AsmTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
433 if (!in_function_) {
434 FAIL(stmt, "do statement inside module body");
435 }
436 RECURSE(Visit(stmt->body()));
437 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
438 "do condition expected to be integer"));
439}
440
441
442void AsmTyper::VisitWhileStatement(WhileStatement* stmt) {
443 if (!in_function_) {
444 FAIL(stmt, "while statement inside module body");
445 }
446 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
447 "while condition expected to be integer"));
448 RECURSE(Visit(stmt->body()));
449}
450
451
452void AsmTyper::VisitForStatement(ForStatement* stmt) {
453 if (!in_function_) {
454 FAIL(stmt, "for statement inside module body");
455 }
Ben Murdochc5610432016-08-08 18:44:38 +0100456 if (stmt->init() != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 RECURSE(Visit(stmt->init()));
458 }
Ben Murdochc5610432016-08-08 18:44:38 +0100459 if (stmt->cond() != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
461 "for condition expected to be integer"));
462 }
Ben Murdochc5610432016-08-08 18:44:38 +0100463 if (stmt->next() != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464 RECURSE(Visit(stmt->next()));
465 }
466 RECURSE(Visit(stmt->body()));
467}
468
469
470void AsmTyper::VisitForInStatement(ForInStatement* stmt) {
471 FAIL(stmt, "for-in statement encountered");
472}
473
474
475void AsmTyper::VisitForOfStatement(ForOfStatement* stmt) {
476 FAIL(stmt, "for-of statement encountered");
477}
478
479
480void AsmTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
481 FAIL(stmt, "try statement encountered");
482}
483
484
485void AsmTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
486 FAIL(stmt, "try statement encountered");
487}
488
489
490void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
491 FAIL(stmt, "debugger statement encountered");
492}
493
494
495void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000496 if (in_function_) {
497 FAIL(expr, "invalid nested function");
498 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100499 Scope* scope = expr->scope();
500 DCHECK(scope->is_function_scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000501
Ben Murdochc5610432016-08-08 18:44:38 +0100502 if (!bounds_.get(expr).upper->IsFunction()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503 FAIL(expr, "invalid function literal");
504 }
505
Ben Murdochc5610432016-08-08 18:44:38 +0100506 Type* type = bounds_.get(expr).upper;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000507 Type* save_return_type = return_type_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100508 return_type_ = type->AsFunction()->Result();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509 in_function_ = true;
510 local_variable_type_.Clear();
511 RECURSE(VisitDeclarations(scope->declarations()));
512 RECURSE(VisitStatements(expr->body()));
513 in_function_ = false;
514 return_type_ = save_return_type;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100515 RECURSE(IntersectResult(expr, type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000516}
517
518
519void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
520 FAIL(expr, "function info literal encountered");
521}
522
523
524void AsmTyper::VisitDoExpression(DoExpression* expr) {
525 FAIL(expr, "do-expression encountered");
526}
527
528
529void AsmTyper::VisitConditional(Conditional* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100530 if (!in_function_) {
531 FAIL(expr, "ternary operator inside module body");
532 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000533 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(),
534 "condition expected to be integer"));
535 if (!computed_type_->Is(cache_.kAsmInt)) {
536 FAIL(expr->condition(), "condition must be of type int");
537 }
538
539 RECURSE(VisitWithExpectation(
540 expr->then_expression(), expected_type_,
541 "conditional then branch type mismatch with enclosing expression"));
542 Type* then_type = StorageType(computed_type_);
543 if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) {
544 FAIL(expr->then_expression(), "invalid type in ? then expression");
545 }
546
547 RECURSE(VisitWithExpectation(
548 expr->else_expression(), expected_type_,
549 "conditional else branch type mismatch with enclosing expression"));
550 Type* else_type = StorageType(computed_type_);
551 if (intish_ != 0 || !else_type->Is(cache_.kAsmComparable)) {
552 FAIL(expr->else_expression(), "invalid type in ? else expression");
553 }
554
555 if (!then_type->Is(else_type) || !else_type->Is(then_type)) {
556 FAIL(expr, "then and else expressions in ? must have the same type");
557 }
558
Ben Murdoch61f157c2016-09-16 13:49:30 +0100559 RECURSE(IntersectResult(expr, then_type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560}
561
562
563void AsmTyper::VisitVariableProxy(VariableProxy* expr) {
564 Variable* var = expr->var();
Ben Murdochc5610432016-08-08 18:44:38 +0100565 VariableInfo* info = GetVariableInfo(var);
566 if (!in_function_ && !building_function_tables_ && !visiting_exports_) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100567 if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) {
568 FAIL(expr, "illegal variable reference in module body");
569 }
570 }
Ben Murdochc5610432016-08-08 18:44:38 +0100571 if (info == nullptr || info->type == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000572 if (var->mode() == TEMPORARY) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100573 SetType(var, Type::Any());
Ben Murdochc5610432016-08-08 18:44:38 +0100574 info = GetVariableInfo(var);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000575 } else {
576 FAIL(expr, "unbound variable");
577 }
578 }
Ben Murdochc5610432016-08-08 18:44:38 +0100579 if (property_info_ != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 SetVariableInfo(var, property_info_);
Ben Murdochc5610432016-08-08 18:44:38 +0100581 property_info_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 }
583 Type* type = Type::Intersect(info->type, expected_type_, zone());
Ben Murdochc5610432016-08-08 18:44:38 +0100584 if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 intish_ = 0;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100586 RECURSE(IntersectResult(expr, type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000587}
588
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000589void AsmTyper::VisitLiteral(Literal* expr, bool is_return) {
590 intish_ = 0;
591 Handle<Object> value = expr->value();
592 if (value->IsNumber()) {
593 int32_t i;
594 uint32_t u;
595 if (expr->raw_value()->ContainsDot()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100596 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000597 } else if (!is_return && value->ToUint32(&u)) {
598 if (u <= 0x7fffffff) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100599 RECURSE(IntersectResult(expr, cache_.kAsmFixnum));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100601 RECURSE(IntersectResult(expr, cache_.kAsmUnsigned));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 }
603 } else if (value->ToInt32(&i)) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100604 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605 } else {
606 FAIL(expr, "illegal number");
607 }
608 } else if (!is_return && value->IsString()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100609 RECURSE(IntersectResult(expr, Type::String()));
610 } else if (value->IsUndefined(isolate_)) {
611 RECURSE(IntersectResult(expr, Type::Undefined()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 } else {
613 FAIL(expr, "illegal literal");
614 }
615}
616
617
618void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); }
619
620
621void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
622 FAIL(expr, "regular expression encountered");
623}
624
625
626void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) {
627 if (in_function_) {
628 FAIL(expr, "object literal in function");
629 }
630 // Allowed for asm module's export declaration.
631 ZoneList<ObjectLiteralProperty*>* props = expr->properties();
632 for (int i = 0; i < props->length(); ++i) {
633 ObjectLiteralProperty* prop = props->at(i);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100634 RECURSE(VisitWithExpectation(prop->value(), Type::Any(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 "object property expected to be a function"));
636 if (!computed_type_->IsFunction()) {
637 FAIL(prop->value(), "non-function in function table");
638 }
639 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100640 RECURSE(IntersectResult(expr, Type::Object()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000641}
642
643
644void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) {
645 if (in_function_) {
646 FAIL(expr, "array literal inside a function");
647 }
648 // Allowed for function tables.
649 ZoneList<Expression*>* values = expr->values();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100650 Type* elem_type = Type::None();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000651 for (int i = 0; i < values->length(); ++i) {
652 Expression* value = values->at(i);
653 RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE"));
654 if (!computed_type_->IsFunction()) {
655 FAIL(value, "array component expected to be a function");
656 }
657 elem_type = Type::Union(elem_type, computed_type_, zone());
658 }
659 array_size_ = values->length();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100660 RECURSE(IntersectResult(expr, Type::Array(elem_type, zone())));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000661}
662
663
664void AsmTyper::VisitAssignment(Assignment* expr) {
665 // Handle function tables and everything else in different passes.
666 if (!in_function_) {
667 if (expr->value()->IsArrayLiteral()) {
668 if (!building_function_tables_) {
669 return;
670 }
671 } else {
672 if (building_function_tables_) {
673 return;
674 }
675 }
676 }
677 if (expr->is_compound()) FAIL(expr, "compound assignment encountered");
678 Type* type = expected_type_;
679 RECURSE(VisitWithExpectation(
680 expr->value(), type, "assignment value expected to match surrounding"));
681 Type* target_type = StorageType(computed_type_);
Ben Murdochc5610432016-08-08 18:44:38 +0100682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 if (expr->target()->IsVariableProxy()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100684 // Assignment to a local or context variable.
685 VariableProxy* proxy = expr->target()->AsVariableProxy();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100686 if (intish_ != 0) {
687 FAIL(expr, "intish or floatish assignment");
688 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100689 if (in_function_ && target_type->IsArray()) {
690 FAIL(expr, "assignment to array variable");
691 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100692 expected_type_ = target_type;
Ben Murdochc5610432016-08-08 18:44:38 +0100693 Variable* var = proxy->var();
694 VariableInfo* info = GetVariableInfo(var);
695 if (info == nullptr || info->type == nullptr) {
696 if (var->mode() == TEMPORARY) {
697 SetType(var, Type::Any());
698 info = GetVariableInfo(var);
699 } else {
700 FAIL(proxy, "unbound variable");
701 }
702 }
703 if (property_info_ != nullptr) {
704 SetVariableInfo(var, property_info_);
705 property_info_ = nullptr;
706 }
707 Type* type = Type::Intersect(info->type, expected_type_, zone());
708 if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt;
709 info->type = type;
710 intish_ = 0;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100711 RECURSE(IntersectResult(proxy, type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 } else if (expr->target()->IsProperty()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100713 // Assignment to a property: should be a heap assignment {H[x] = y}.
Ben Murdochda12d292016-06-02 14:46:10 +0100714 int32_t value_intish = intish_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000715 Property* property = expr->target()->AsProperty();
716 RECURSE(VisitWithExpectation(property->obj(), Type::Any(),
717 "bad propety object"));
718 if (!computed_type_->IsArray()) {
719 FAIL(property->obj(), "array expected");
720 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100721 if (value_intish != 0 && computed_type_->Is(cache_.kFloat64Array)) {
722 FAIL(expr, "floatish assignment to double array");
723 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000724 VisitHeapAccess(property, true, target_type);
725 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100726 RECURSE(IntersectResult(expr, target_type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000727}
728
729
730void AsmTyper::VisitYield(Yield* expr) {
731 FAIL(expr, "yield expression encountered");
732}
733
734
735void AsmTyper::VisitThrow(Throw* expr) {
736 FAIL(expr, "throw statement encountered");
737}
738
739
740int AsmTyper::ElementShiftSize(Type* type) {
741 if (type->Is(cache_.kAsmSize8)) return 0;
742 if (type->Is(cache_.kAsmSize16)) return 1;
743 if (type->Is(cache_.kAsmSize32)) return 2;
744 if (type->Is(cache_.kAsmSize64)) return 3;
745 return -1;
746}
747
748
749Type* AsmTyper::StorageType(Type* type) {
750 if (type->Is(cache_.kAsmInt)) {
751 return cache_.kAsmInt;
752 } else {
753 return type;
754 }
755}
756
757
758void AsmTyper::VisitHeapAccess(Property* expr, bool assigning,
759 Type* assignment_type) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100760 ArrayType* array_type = computed_type_->AsArray();
761 // size_t size = array_size_;
762 Type* type = array_type->Element();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000763 if (type->IsFunction()) {
764 if (assigning) {
765 FAIL(expr, "assigning to function table is illegal");
766 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100767 // TODO(bradnelson): Fix the parser and then un-comment this part
768 // BinaryOperation* bin = expr->key()->AsBinaryOperation();
Ben Murdochc5610432016-08-08 18:44:38 +0100769 // if (bin == nullptr || bin->op() != Token::BIT_AND) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100770 // FAIL(expr->key(), "expected & in call");
771 // }
772 // RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned,
773 // "array index expected to be integer"));
774 // Literal* right = bin->right()->AsLiteral();
Ben Murdochc5610432016-08-08 18:44:38 +0100775 // if (right == nullptr || right->raw_value()->ContainsDot()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100776 // FAIL(right, "call mask must be integer");
777 // }
778 // RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
779 // "call mask expected to be integer"));
780 // if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) {
781 // FAIL(right, "call mask must match function table");
782 // }
783 // bin->set_bounds(Bounds(cache_.kAsmSigned));
784 RECURSE(VisitWithExpectation(expr->key(), cache_.kAsmSigned,
785 "must be integer"));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100786 RECURSE(IntersectResult(expr, type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000787 } else {
788 Literal* literal = expr->key()->AsLiteral();
789 if (literal) {
790 RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned,
791 "array index expected to be integer"));
792 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793 int expected_shift = ElementShiftSize(type);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100794 if (expected_shift == 0) {
795 RECURSE(Visit(expr->key()));
796 } else {
797 BinaryOperation* bin = expr->key()->AsBinaryOperation();
Ben Murdochc5610432016-08-08 18:44:38 +0100798 if (bin == nullptr || bin->op() != Token::SAR) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100799 FAIL(expr->key(), "expected >> in heap access");
800 }
801 RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned,
802 "array index expected to be integer"));
803 Literal* right = bin->right()->AsLiteral();
Ben Murdochc5610432016-08-08 18:44:38 +0100804 if (right == nullptr || right->raw_value()->ContainsDot()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100805 FAIL(bin->right(), "heap access shift must be integer");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100806 }
807 RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
808 "array shift expected to be integer"));
809 int n = static_cast<int>(right->raw_value()->AsNumber());
810 if (expected_shift < 0 || n != expected_shift) {
811 FAIL(right, "heap access shift must match element size");
812 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000813 }
Ben Murdochc5610432016-08-08 18:44:38 +0100814 bounds_.set(expr->key(), Bounds(cache_.kAsmSigned));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000815 }
816 Type* result_type;
817 if (type->Is(cache_.kAsmIntArrayElement)) {
818 result_type = cache_.kAsmIntQ;
819 intish_ = kMaxUncombinedAdditiveSteps;
820 } else if (type->Is(cache_.kAsmFloat)) {
821 if (assigning) {
822 result_type = cache_.kAsmFloatDoubleQ;
823 } else {
824 result_type = cache_.kAsmFloatQ;
825 }
826 intish_ = 0;
827 } else if (type->Is(cache_.kAsmDouble)) {
828 if (assigning) {
829 result_type = cache_.kAsmFloatDoubleQ;
830 if (intish_ != 0) {
831 FAIL(expr, "Assignment of floatish to Float64Array");
832 }
833 } else {
834 result_type = cache_.kAsmDoubleQ;
835 }
836 intish_ = 0;
837 } else {
838 UNREACHABLE();
839 }
840 if (assigning) {
841 if (!assignment_type->Is(result_type)) {
842 FAIL(expr, "illegal type in assignment");
843 }
844 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100845 RECURSE(IntersectResult(expr, expected_type_));
846 RECURSE(IntersectResult(expr, result_type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000847 }
848 }
849}
850
851
852bool AsmTyper::IsStdlibObject(Expression* expr) {
853 VariableProxy* proxy = expr->AsVariableProxy();
Ben Murdochc5610432016-08-08 18:44:38 +0100854 if (proxy == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000855 return false;
856 }
857 Variable* var = proxy->var();
Ben Murdochc5610432016-08-08 18:44:38 +0100858 VariableInfo* info = GetVariableInfo(var);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000859 if (info) {
860 if (info->standard_member == kStdlib) return true;
861 }
862 if (var->location() != VariableLocation::PARAMETER || var->index() != 0) {
863 return false;
864 }
Ben Murdochc5610432016-08-08 18:44:38 +0100865 info = MakeVariableInfo(var);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 info->type = Type::Object();
867 info->standard_member = kStdlib;
868 return true;
869}
870
871
872Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr,
873 const char* name) {
874 Property* property = expr->AsProperty();
Ben Murdochc5610432016-08-08 18:44:38 +0100875 if (property == nullptr) {
876 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000877 }
878 Literal* key = property->key()->AsLiteral();
Ben Murdochc5610432016-08-08 18:44:38 +0100879 if (key == nullptr || !key->IsPropertyName() ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) {
Ben Murdochc5610432016-08-08 18:44:38 +0100881 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000882 }
883 return property->obj();
884}
885
886
887bool AsmTyper::IsMathObject(Expression* expr) {
888 Expression* obj = GetReceiverOfPropertyAccess(expr, "Math");
889 return obj && IsStdlibObject(obj);
890}
891
892
893bool AsmTyper::IsSIMDObject(Expression* expr) {
894 Expression* obj = GetReceiverOfPropertyAccess(expr, "SIMD");
895 return obj && IsStdlibObject(obj);
896}
897
898
899bool AsmTyper::IsSIMDTypeObject(Expression* expr, const char* name) {
900 Expression* obj = GetReceiverOfPropertyAccess(expr, name);
901 return obj && IsSIMDObject(obj);
902}
903
904
905void AsmTyper::VisitProperty(Property* expr) {
906 if (IsMathObject(expr->obj())) {
907 VisitLibraryAccess(&stdlib_math_types_, expr);
908 return;
909 }
910#define V(NAME, Name, name, lane_count, lane_type) \
911 if (IsSIMDTypeObject(expr->obj(), #Name)) { \
912 VisitLibraryAccess(&stdlib_simd_##name##_types_, expr); \
913 return; \
914 } \
915 if (IsSIMDTypeObject(expr, #Name)) { \
916 VariableInfo* info = stdlib_simd_##name##_constructor_type_; \
917 SetResult(expr, info->type); \
918 property_info_ = info; \
919 return; \
920 }
921 SIMD128_TYPES(V)
922#undef V
923 if (IsStdlibObject(expr->obj())) {
924 VisitLibraryAccess(&stdlib_types_, expr);
925 return;
926 }
927
Ben Murdochc5610432016-08-08 18:44:38 +0100928 property_info_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929
930 // Only recurse at this point so that we avoid needing
931 // stdlib.Math to have a real type.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100932 RECURSE(
933 VisitWithExpectation(expr->obj(), Type::Any(), "bad property object"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000934
935 // For heap view or function table access.
936 if (computed_type_->IsArray()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100937 VisitHeapAccess(expr, false, nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000938 return;
939 }
940
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000941 VariableProxy* proxy = expr->obj()->AsVariableProxy();
Ben Murdochc5610432016-08-08 18:44:38 +0100942 if (proxy != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000943 Variable* var = proxy->var();
944 if (var->location() == VariableLocation::PARAMETER && var->index() == 1) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100945 // foreign.x - Function represent as () -> Any
946 if (Type::Any()->Is(expected_type_)) {
947 SetResult(expr, Type::Function(Type::Any(), zone()));
948 } else {
949 SetResult(expr, expected_type_);
950 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 return;
952 }
953 }
954
955 FAIL(expr, "invalid property access");
956}
957
Ben Murdochda12d292016-06-02 14:46:10 +0100958void AsmTyper::CheckPolymorphicStdlibArguments(
959 enum StandardMember standard_member, ZoneList<Expression*>* args) {
960 if (args->length() == 0) {
961 return;
962 }
963 // Handle polymorphic stdlib functions specially.
964 Expression* arg0 = args->at(0);
Ben Murdochc5610432016-08-08 18:44:38 +0100965 Type* arg0_type = bounds_.get(arg0).upper;
Ben Murdochda12d292016-06-02 14:46:10 +0100966 switch (standard_member) {
967 case kMathFround: {
968 if (!arg0_type->Is(cache_.kAsmFloat) &&
969 !arg0_type->Is(cache_.kAsmDouble) &&
970 !arg0_type->Is(cache_.kAsmSigned) &&
971 !arg0_type->Is(cache_.kAsmUnsigned)) {
972 FAIL(arg0, "illegal function argument type");
973 }
974 break;
975 }
976 case kMathCeil:
977 case kMathFloor:
978 case kMathSqrt: {
979 if (!arg0_type->Is(cache_.kAsmFloat) &&
980 !arg0_type->Is(cache_.kAsmDouble)) {
981 FAIL(arg0, "illegal function argument type");
982 }
983 break;
984 }
985 case kMathAbs:
986 case kMathMin:
987 case kMathMax: {
988 if (!arg0_type->Is(cache_.kAsmFloat) &&
989 !arg0_type->Is(cache_.kAsmDouble) &&
990 !arg0_type->Is(cache_.kAsmSigned)) {
991 FAIL(arg0, "illegal function argument type");
992 }
993 if (args->length() > 1) {
Ben Murdochc5610432016-08-08 18:44:38 +0100994 Type* other = Type::Intersect(bounds_.get(args->at(0)).upper,
995 bounds_.get(args->at(1)).upper, zone());
Ben Murdochda12d292016-06-02 14:46:10 +0100996 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) &&
997 !other->Is(cache_.kAsmSigned)) {
998 FAIL(arg0, "function arguments types don't match");
999 }
1000 }
1001 break;
1002 }
1003 default: { break; }
1004 }
1005}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001006
1007void AsmTyper::VisitCall(Call* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001008 Type* expected_type = expected_type_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001009 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
1010 "callee expected to be any"));
1011 StandardMember standard_member = kNone;
1012 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1013 if (proxy) {
1014 standard_member = VariableAsStandardMember(proxy->var());
1015 }
Ben Murdochc5610432016-08-08 18:44:38 +01001016 if (!in_function_ && (proxy == nullptr || standard_member != kMathFround)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001017 FAIL(expr, "calls forbidden outside function bodies");
1018 }
Ben Murdochc5610432016-08-08 18:44:38 +01001019 if (proxy == nullptr && !expr->expression()->IsProperty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001020 FAIL(expr, "calls must be to bound variables or function tables");
1021 }
1022 if (computed_type_->IsFunction()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001023 FunctionType* fun_type = computed_type_->AsFunction();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001024 Type* result_type = fun_type->Result();
1025 ZoneList<Expression*>* args = expr->arguments();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001026 if (Type::Any()->Is(result_type)) {
1027 // For foreign calls.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001028 for (int i = 0; i < args->length(); ++i) {
1029 Expression* arg = args->at(i);
1030 RECURSE(VisitWithExpectation(
1031 arg, Type::Any(), "foreign call argument expected to be any"));
1032 // Checking for asm extern types explicitly, as the type system
1033 // doesn't correctly check their inheritance relationship.
1034 if (!computed_type_->Is(cache_.kAsmSigned) &&
1035 !computed_type_->Is(cache_.kAsmFixnum) &&
1036 !computed_type_->Is(cache_.kAsmDouble)) {
1037 FAIL(arg,
1038 "foreign call argument expected to be int, double, or fixnum");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001039 }
1040 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001041 intish_ = 0;
Ben Murdochc5610432016-08-08 18:44:38 +01001042 bounds_.set(expr->expression(),
1043 Bounds(Type::Function(Type::Any(), zone())));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001044 RECURSE(IntersectResult(expr, expected_type));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001045 } else {
1046 if (fun_type->Arity() != args->length()) {
1047 FAIL(expr, "call with wrong arity");
1048 }
1049 for (int i = 0; i < args->length(); ++i) {
1050 Expression* arg = args->at(i);
1051 RECURSE(VisitWithExpectation(
1052 arg, fun_type->Parameter(i),
1053 "call argument expected to match callee parameter"));
1054 if (standard_member != kNone && standard_member != kMathFround &&
1055 i == 0) {
1056 result_type = computed_type_;
1057 }
1058 }
Ben Murdochda12d292016-06-02 14:46:10 +01001059 RECURSE(CheckPolymorphicStdlibArguments(standard_member, args));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001060 intish_ = 0;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001061 RECURSE(IntersectResult(expr, result_type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001062 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001063 } else {
1064 FAIL(expr, "invalid callee");
1065 }
1066}
1067
1068
1069void AsmTyper::VisitCallNew(CallNew* expr) {
1070 if (in_function_) {
1071 FAIL(expr, "new not allowed in module function");
1072 }
1073 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
1074 "expected stdlib function"));
1075 if (computed_type_->IsFunction()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001076 FunctionType* fun_type = computed_type_->AsFunction();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001077 ZoneList<Expression*>* args = expr->arguments();
1078 if (fun_type->Arity() != args->length())
1079 FAIL(expr, "call with wrong arity");
1080 for (int i = 0; i < args->length(); ++i) {
1081 Expression* arg = args->at(i);
1082 RECURSE(VisitWithExpectation(
1083 arg, fun_type->Parameter(i),
1084 "constructor argument expected to match callee parameter"));
1085 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001086 RECURSE(IntersectResult(expr, fun_type->Result()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001087 return;
1088 }
1089
1090 FAIL(expr, "ill-typed new operator");
1091}
1092
1093
1094void AsmTyper::VisitCallRuntime(CallRuntime* expr) {
Ben Murdochc5610432016-08-08 18:44:38 +01001095 FAIL(expr, "runtime call not allowed");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001096}
1097
1098
1099void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001100 if (!in_function_) {
1101 FAIL(expr, "unary operator inside module body");
1102 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001103 switch (expr->op()) {
1104 case Token::NOT: // Used to encode != and !==
1105 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt,
1106 "operand expected to be integer"));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001107 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108 return;
1109 case Token::DELETE:
1110 FAIL(expr, "delete operator encountered");
1111 case Token::VOID:
1112 FAIL(expr, "void operator encountered");
1113 case Token::TYPEOF:
1114 FAIL(expr, "typeof operator encountered");
1115 default:
1116 UNREACHABLE();
1117 }
1118}
1119
1120
1121void AsmTyper::VisitCountOperation(CountOperation* expr) {
1122 FAIL(expr, "increment or decrement operator encountered");
1123}
1124
1125
1126void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
1127 Type* left_expected,
1128 Type* right_expected,
1129 Type* result_type, bool conversion) {
1130 RECURSE(VisitWithExpectation(expr->left(), Type::Number(),
1131 "left bitwise operand expected to be a number"));
Ben Murdochda12d292016-06-02 14:46:10 +01001132 int32_t left_intish = intish_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001133 Type* left_type = computed_type_;
1134 if (!left_type->Is(left_expected)) {
1135 FAIL(expr->left(), "left bitwise operand expected to be an integer");
1136 }
1137 if (left_intish > kMaxUncombinedAdditiveSteps) {
1138 FAIL(expr->left(), "too many consecutive additive ops");
1139 }
1140
1141 RECURSE(
1142 VisitWithExpectation(expr->right(), Type::Number(),
1143 "right bitwise operand expected to be a number"));
Ben Murdochda12d292016-06-02 14:46:10 +01001144 int32_t right_intish = intish_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001145 Type* right_type = computed_type_;
1146 if (!right_type->Is(right_expected)) {
1147 FAIL(expr->right(), "right bitwise operand expected to be an integer");
1148 }
1149 if (right_intish > kMaxUncombinedAdditiveSteps) {
1150 FAIL(expr->right(), "too many consecutive additive ops");
1151 }
1152
1153 intish_ = 0;
1154
1155 if (left_type->Is(cache_.kAsmFixnum) && right_type->Is(cache_.kAsmInt)) {
1156 left_type = right_type;
1157 }
1158 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) {
1159 right_type = left_type;
1160 }
1161 if (!conversion) {
Ben Murdochda12d292016-06-02 14:46:10 +01001162 if (!left_type->Is(cache_.kAsmIntQ) || !right_type->Is(cache_.kAsmIntQ)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001163 FAIL(expr, "ill-typed bitwise operation");
1164 }
1165 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001166 RECURSE(IntersectResult(expr, result_type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001167}
1168
1169
1170void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001171 if (!in_function_) {
1172 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) {
1173 FAIL(expr, "illegal binary operator inside module body");
1174 }
1175 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) ||
1176 !expr->right()->IsLiteral()) {
1177 FAIL(expr, "illegal computation inside module body");
1178 }
1179 DCHECK(expr->right()->AsLiteral() != nullptr);
1180 const AstValue* right_value = expr->right()->AsLiteral()->raw_value();
1181 if (expr->op() == Token::BIT_OR) {
1182 if (right_value->AsNumber() != 0.0 || right_value->ContainsDot()) {
1183 FAIL(expr, "illegal integer annotation value");
1184 }
1185 }
1186 if (expr->op() == Token::MUL) {
1187 if (right_value->AsNumber() != 1.0 && right_value->ContainsDot()) {
1188 FAIL(expr, "illegal double annotation value");
1189 }
1190 }
1191 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192 switch (expr->op()) {
1193 case Token::COMMA: {
1194 RECURSE(VisitWithExpectation(expr->left(), Type::Any(),
1195 "left comma operand expected to be any"));
1196 RECURSE(VisitWithExpectation(expr->right(), Type::Any(),
1197 "right comma operand expected to be any"));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001198 RECURSE(IntersectResult(expr, computed_type_));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001199 return;
1200 }
1201 case Token::OR:
1202 case Token::AND:
1203 FAIL(expr, "illegal logical operator");
1204 case Token::BIT_OR: {
1205 // BIT_OR allows Any since it is used as a type coercion.
Ben Murdochda12d292016-06-02 14:46:10 +01001206 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ,
1207 cache_.kAsmSigned, true));
1208 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR &&
Ben Murdochc5610432016-08-08 18:44:38 +01001209 Type::Number()->Is(bounds_.get(expr->left()).upper)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001210 // Force the return types of foreign functions.
Ben Murdochc5610432016-08-08 18:44:38 +01001211 bounds_.set(expr->left(), Bounds(cache_.kAsmSigned));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001212 }
Ben Murdochc5610432016-08-08 18:44:38 +01001213 if (in_function_ &&
1214 !bounds_.get(expr->left()).upper->Is(cache_.kAsmIntQ)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001215 FAIL(expr->left(), "intish required");
1216 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001217 return;
1218 }
1219 case Token::BIT_XOR: {
1220 // Handle booleans specially to handle de-sugared !
1221 Literal* left = expr->left()->AsLiteral();
1222 if (left && left->value()->IsBoolean()) {
1223 if (left->ToBooleanIsTrue()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001224 bounds_.set(left, Bounds(cache_.kSingletonOne));
Ben Murdochda12d292016-06-02 14:46:10 +01001225 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmIntQ,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226 "not operator expects an integer"));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001227 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 return;
1229 } else {
1230 FAIL(left, "unexpected false");
1231 }
1232 }
Ben Murdochda12d292016-06-02 14:46:10 +01001233 // BIT_XOR allows Any since it is used as a type coercion (via ~~).
1234 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ,
1235 cache_.kAsmSigned, true));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001236 return;
1237 }
1238 case Token::SHR: {
Ben Murdochda12d292016-06-02 14:46:10 +01001239 RECURSE(VisitIntegerBitwiseOperator(
1240 expr, cache_.kAsmIntQ, cache_.kAsmIntQ, cache_.kAsmUnsigned, false));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001241 return;
1242 }
1243 case Token::SHL:
1244 case Token::SAR:
1245 case Token::BIT_AND: {
Ben Murdochda12d292016-06-02 14:46:10 +01001246 RECURSE(VisitIntegerBitwiseOperator(
1247 expr, cache_.kAsmIntQ, cache_.kAsmIntQ, cache_.kAsmSigned, false));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001248 return;
1249 }
1250 case Token::ADD:
1251 case Token::SUB:
1252 case Token::MUL:
1253 case Token::DIV:
1254 case Token::MOD: {
1255 RECURSE(VisitWithExpectation(
1256 expr->left(), Type::Number(),
1257 "left arithmetic operand expected to be number"));
1258 Type* left_type = computed_type_;
Ben Murdochda12d292016-06-02 14:46:10 +01001259 int32_t left_intish = intish_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001260 RECURSE(VisitWithExpectation(
1261 expr->right(), Type::Number(),
1262 "right arithmetic operand expected to be number"));
1263 Type* right_type = computed_type_;
Ben Murdochda12d292016-06-02 14:46:10 +01001264 int32_t right_intish = intish_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001265 Type* type = Type::Union(left_type, right_type, zone());
1266 if (type->Is(cache_.kAsmInt)) {
1267 if (expr->op() == Token::MUL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001268 int32_t i;
Ben Murdochda12d292016-06-02 14:46:10 +01001269 Literal* left = expr->left()->AsLiteral();
1270 Literal* right = expr->right()->AsLiteral();
1271 if (left != nullptr && left->value()->IsNumber() &&
1272 left->value()->ToInt32(&i)) {
1273 if (right_intish != 0) {
1274 FAIL(expr, "intish not allowed in multiply");
1275 }
1276 } else if (right != nullptr && right->value()->IsNumber() &&
1277 right->value()->ToInt32(&i)) {
1278 if (left_intish != 0) {
1279 FAIL(expr, "intish not allowed in multiply");
1280 }
1281 } else {
1282 FAIL(expr, "multiply must be by an integer literal");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001283 }
1284 i = abs(i);
Ben Murdochda12d292016-06-02 14:46:10 +01001285 if (i >= (1 << 20)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001286 FAIL(expr, "multiply must be by value in -2^20 < n < 2^20");
1287 }
1288 intish_ = i;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001289 RECURSE(IntersectResult(expr, cache_.kAsmInt));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001290 return;
1291 } else {
1292 intish_ = left_intish + right_intish + 1;
1293 if (expr->op() == Token::ADD || expr->op() == Token::SUB) {
1294 if (intish_ > kMaxUncombinedAdditiveSteps) {
1295 FAIL(expr, "too many consecutive additive ops");
1296 }
1297 } else {
1298 if (intish_ > kMaxUncombinedMultiplicativeSteps) {
1299 FAIL(expr, "too many consecutive multiplicative ops");
1300 }
1301 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001302 RECURSE(IntersectResult(expr, cache_.kAsmInt));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001303 return;
1304 }
1305 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() &&
Ben Murdochda12d292016-06-02 14:46:10 +01001306 right_type->Is(cache_.kAsmDouble) &&
1307 expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
1308 expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001309 // For unary +, expressed as x * 1.0
Ben Murdochda12d292016-06-02 14:46:10 +01001310 if (expr->left()->IsCall() &&
Ben Murdochc5610432016-08-08 18:44:38 +01001311 Type::Number()->Is(bounds_.get(expr->left()).upper)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001312 // Force the return types of foreign functions.
Ben Murdochc5610432016-08-08 18:44:38 +01001313 bounds_.set(expr->left(), Bounds(cache_.kAsmDouble));
1314 left_type = bounds_.get(expr->left()).upper;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001315 }
Ben Murdochda12d292016-06-02 14:46:10 +01001316 if (!(expr->left()->IsProperty() &&
Ben Murdochc5610432016-08-08 18:44:38 +01001317 Type::Number()->Is(bounds_.get(expr->left()).upper))) {
Ben Murdochda12d292016-06-02 14:46:10 +01001318 if (!left_type->Is(cache_.kAsmSigned) &&
1319 !left_type->Is(cache_.kAsmUnsigned) &&
1320 !left_type->Is(cache_.kAsmFixnum) &&
1321 !left_type->Is(cache_.kAsmFloatQ) &&
1322 !left_type->Is(cache_.kAsmDoubleQ)) {
1323 FAIL(
1324 expr->left(),
1325 "unary + only allowed on signed, unsigned, float?, or double?");
1326 }
1327 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001328 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
Ben Murdochda12d292016-06-02 14:46:10 +01001329 return;
1330 } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmDouble) &&
1331 expr->right()->IsLiteral() &&
1332 !expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
1333 expr->right()->AsLiteral()->raw_value()->AsNumber() == -1.0) {
1334 // For unary -, expressed as x * -1
Ben Murdochc5610432016-08-08 18:44:38 +01001335 bounds_.set(expr->right(), Bounds(cache_.kAsmDouble));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001336 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001337 return;
1338 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) {
1339 if (left_intish != 0 || right_intish != 0) {
1340 FAIL(expr, "float operation before required fround");
1341 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001342 RECURSE(IntersectResult(expr, cache_.kAsmFloat));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001343 intish_ = 1;
1344 return;
1345 } else if (type->Is(cache_.kAsmDouble)) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001346 RECURSE(IntersectResult(expr, cache_.kAsmDouble));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001347 return;
1348 } else {
1349 FAIL(expr, "ill-typed arithmetic operation");
1350 }
1351 }
1352 default:
1353 UNREACHABLE();
1354 }
1355}
1356
1357
1358void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001359 if (!in_function_) {
1360 FAIL(expr, "comparison inside module body");
1361 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001362 Token::Value op = expr->op();
1363 if (op != Token::EQ && op != Token::NE && op != Token::LT &&
1364 op != Token::LTE && op != Token::GT && op != Token::GTE) {
1365 FAIL(expr, "illegal comparison operator");
1366 }
1367
1368 RECURSE(
1369 VisitWithExpectation(expr->left(), Type::Number(),
1370 "left comparison operand expected to be number"));
1371 Type* left_type = computed_type_;
1372 if (!left_type->Is(cache_.kAsmComparable)) {
1373 FAIL(expr->left(), "bad type on left side of comparison");
1374 }
1375
1376 RECURSE(
1377 VisitWithExpectation(expr->right(), Type::Number(),
1378 "right comparison operand expected to be number"));
1379 Type* right_type = computed_type_;
1380 if (!right_type->Is(cache_.kAsmComparable)) {
1381 FAIL(expr->right(), "bad type on right side of comparison");
1382 }
1383
1384 if (!left_type->Is(right_type) && !right_type->Is(left_type)) {
1385 FAIL(expr, "left and right side of comparison must match");
1386 }
1387
Ben Murdoch61f157c2016-09-16 13:49:30 +01001388 RECURSE(IntersectResult(expr, cache_.kAsmSigned));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001389}
1390
1391
1392void AsmTyper::VisitThisFunction(ThisFunction* expr) {
1393 FAIL(expr, "this function not allowed");
1394}
1395
1396
1397void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
1398 for (int i = 0; i < decls->length(); ++i) {
1399 Declaration* decl = decls->at(i);
1400 RECURSE(Visit(decl));
1401 }
1402}
1403
1404
1405void AsmTyper::VisitImportDeclaration(ImportDeclaration* decl) {
1406 FAIL(decl, "import declaration encountered");
1407}
1408
1409
1410void AsmTyper::VisitExportDeclaration(ExportDeclaration* decl) {
1411 FAIL(decl, "export declaration encountered");
1412}
1413
1414
1415void AsmTyper::VisitClassLiteral(ClassLiteral* expr) {
1416 FAIL(expr, "class literal not allowed");
1417}
1418
1419
1420void AsmTyper::VisitSpread(Spread* expr) { FAIL(expr, "spread not allowed"); }
1421
1422
1423void AsmTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) {
1424 FAIL(expr, "super property reference not allowed");
1425}
1426
1427
1428void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) {
1429 FAIL(expr, "call reference not allowed");
1430}
1431
1432
1433void AsmTyper::InitializeStdlibSIMD() {
1434#define V(NAME, Name, name, lane_count, lane_type) \
1435 { \
1436 Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(), \
1437 lane_count, zone()); \
1438 for (int i = 0; i < lane_count; ++i) { \
1439 type->AsFunction()->InitParameter(i, Type::Number()); \
1440 } \
1441 stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \
1442 stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \
1443 }
1444 SIMD128_TYPES(V)
1445#undef V
1446}
1447
1448
1449void AsmTyper::InitializeStdlib() {
1450 if (allow_simd_) {
1451 InitializeStdlibSIMD();
1452 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001453 Type* number_type = Type::Number();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001454 Type* double_type = cache_.kAsmDouble;
1455 Type* double_fn1_type = Type::Function(double_type, double_type, zone());
1456 Type* double_fn2_type =
1457 Type::Function(double_type, double_type, double_type, zone());
1458
1459 Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone());
1460 Type* imul_type =
1461 Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone());
1462 // TODO(bradnelson): currently only approximating the proper intersection type
1463 // (which we cannot currently represent).
1464 Type* number_fn1_type = Type::Function(number_type, number_type, zone());
1465 Type* number_fn2_type =
1466 Type::Function(number_type, number_type, number_type, zone());
1467
1468 struct Assignment {
1469 const char* name;
1470 StandardMember standard_member;
1471 Type* type;
1472 };
1473
1474 const Assignment math[] = {{"PI", kMathPI, double_type},
1475 {"E", kMathE, double_type},
1476 {"LN2", kMathLN2, double_type},
1477 {"LN10", kMathLN10, double_type},
1478 {"LOG2E", kMathLOG2E, double_type},
1479 {"LOG10E", kMathLOG10E, double_type},
1480 {"SQRT2", kMathSQRT2, double_type},
1481 {"SQRT1_2", kMathSQRT1_2, double_type},
1482 {"imul", kMathImul, imul_type},
1483 {"abs", kMathAbs, number_fn1_type},
1484 {"ceil", kMathCeil, number_fn1_type},
1485 {"floor", kMathFloor, number_fn1_type},
1486 {"fround", kMathFround, fround_type},
1487 {"pow", kMathPow, double_fn2_type},
1488 {"exp", kMathExp, double_fn1_type},
1489 {"log", kMathLog, double_fn1_type},
1490 {"min", kMathMin, number_fn2_type},
1491 {"max", kMathMax, number_fn2_type},
1492 {"sqrt", kMathSqrt, number_fn1_type},
1493 {"cos", kMathCos, double_fn1_type},
1494 {"sin", kMathSin, double_fn1_type},
1495 {"tan", kMathTan, double_fn1_type},
1496 {"acos", kMathAcos, double_fn1_type},
1497 {"asin", kMathAsin, double_fn1_type},
1498 {"atan", kMathAtan, double_fn1_type},
1499 {"atan2", kMathAtan2, double_fn2_type}};
1500 for (unsigned i = 0; i < arraysize(math); ++i) {
1501 stdlib_math_types_[math[i].name] = new (zone()) VariableInfo(math[i].type);
1502 stdlib_math_types_[math[i].name]->standard_member = math[i].standard_member;
1503 }
1504 stdlib_math_types_["fround"]->is_check_function = true;
1505
1506 stdlib_types_["Infinity"] = new (zone()) VariableInfo(double_type);
1507 stdlib_types_["Infinity"]->standard_member = kInfinity;
1508 stdlib_types_["NaN"] = new (zone()) VariableInfo(double_type);
1509 stdlib_types_["NaN"]->standard_member = kNaN;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001510 Type* buffer_type = Type::Any();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001511#define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
1512 stdlib_types_[#TypeName "Array"] = new (zone()) VariableInfo( \
1513 Type::Function(cache_.k##TypeName##Array, buffer_type, zone()));
1514 TYPED_ARRAYS(TYPED_ARRAY)
1515#undef TYPED_ARRAY
1516
1517#define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
1518 stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \
1519 Type::Function(cache_.k##TypeName##Array, buffer_type, zone()));
1520 TYPED_ARRAYS(TYPED_ARRAY)
1521#undef TYPED_ARRAY
1522}
1523
1524
1525void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) {
1526 Literal* key = expr->key()->AsLiteral();
Ben Murdochc5610432016-08-08 18:44:38 +01001527 if (key == nullptr || !key->IsPropertyName())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001528 FAIL(expr, "invalid key used on stdlib member");
1529 Handle<String> name = key->AsPropertyName();
1530 VariableInfo* info = LibType(map, name);
Ben Murdochc5610432016-08-08 18:44:38 +01001531 if (info == nullptr || info->type == nullptr)
1532 FAIL(expr, "unknown stdlib function");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001533 SetResult(expr, info->type);
1534 property_info_ = info;
1535}
1536
1537
1538AsmTyper::VariableInfo* AsmTyper::LibType(ObjectTypeMap* map,
1539 Handle<String> name) {
1540 base::SmartArrayPointer<char> aname = name->ToCString();
1541 ObjectTypeMap::iterator i = map->find(std::string(aname.get()));
1542 if (i == map->end()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001543 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001544 }
1545 return i->second;
1546}
1547
1548
1549void AsmTyper::SetType(Variable* variable, Type* type) {
Ben Murdochc5610432016-08-08 18:44:38 +01001550 VariableInfo* info = MakeVariableInfo(variable);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551 info->type = type;
1552}
1553
1554
1555Type* AsmTyper::GetType(Variable* variable) {
Ben Murdochc5610432016-08-08 18:44:38 +01001556 VariableInfo* info = GetVariableInfo(variable);
1557 if (!info) return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001558 return info->type;
1559}
1560
Ben Murdochc5610432016-08-08 18:44:38 +01001561AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable) {
1562 ZoneHashMap* map =
1563 in_function_ ? &local_variable_type_ : &global_variable_type_;
1564 ZoneHashMap::Entry* entry =
1565 map->Lookup(variable, ComputePointerHash(variable));
1566 if (!entry && in_function_) {
1567 entry =
1568 global_variable_type_.Lookup(variable, ComputePointerHash(variable));
1569 }
1570 return entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr;
1571}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001572
Ben Murdochc5610432016-08-08 18:44:38 +01001573AsmTyper::VariableInfo* AsmTyper::MakeVariableInfo(Variable* variable) {
1574 ZoneHashMap* map =
1575 in_function_ ? &local_variable_type_ : &global_variable_type_;
1576 ZoneHashMap::Entry* entry = map->LookupOrInsert(
1577 variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone()));
1578 if (!entry->value) entry->value = new (zone()) VariableInfo;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001579 return reinterpret_cast<VariableInfo*>(entry->value);
1580}
1581
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001582void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) {
Ben Murdochc5610432016-08-08 18:44:38 +01001583 VariableInfo* dest = MakeVariableInfo(variable);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001584 dest->type = info->type;
1585 dest->is_check_function = info->is_check_function;
1586 dest->is_constructor_function = info->is_constructor_function;
1587 dest->standard_member = info->standard_member;
1588}
1589
1590
1591AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(
1592 Variable* variable) {
Ben Murdochc5610432016-08-08 18:44:38 +01001593 VariableInfo* info = GetVariableInfo(variable);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001594 if (!info) return kNone;
1595 return info->standard_member;
1596}
1597
1598
1599void AsmTyper::SetResult(Expression* expr, Type* type) {
1600 computed_type_ = type;
Ben Murdochc5610432016-08-08 18:44:38 +01001601 bounds_.set(expr, Bounds(computed_type_));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001602}
1603
1604
1605void AsmTyper::IntersectResult(Expression* expr, Type* type) {
1606 computed_type_ = type;
1607 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001608 if (Type::Representation(bounded_type, zone())->Is(Type::None())) {
1609#ifdef DEBUG
1610 PrintF("Computed type: ");
1611 computed_type_->Print();
1612 PrintF("Expected type: ");
1613 expected_type_->Print();
1614#endif
1615 FAIL(expr, "type mismatch");
1616 }
Ben Murdochc5610432016-08-08 18:44:38 +01001617 bounds_.set(expr, Bounds(bounded_type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001618}
1619
1620
1621void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type,
1622 const char* msg) {
1623 Type* save = expected_type_;
1624 expected_type_ = expected_type;
1625 RECURSE(Visit(expr));
1626 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001627 if (Type::Representation(bounded_type, zone())->Is(Type::None())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001628#ifdef DEBUG
1629 PrintF("Computed type: ");
1630 computed_type_->Print();
1631 PrintF("Expected type: ");
1632 expected_type_->Print();
1633#endif
1634 FAIL(expr, msg);
1635 }
1636 expected_type_ = save;
1637}
1638
1639
Ben Murdoch097c5b22016-05-18 11:27:45 +01001640void AsmTyper::VisitRewritableExpression(RewritableExpression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001641 RECURSE(Visit(expr->expression()));
1642}
1643
1644
1645} // namespace internal
1646} // namespace v8