Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(478)

Side by Side Diff: src/typing-asm.cc

Issue 1161393007: OLD type Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/typing-asm.h ('k') | src/variables.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #if 0
29 #include "typing-asm.h"
30
31 #include "parser.h" // for CompileTimeValue; TODO(rossberg): should move
32 #include "scopes.h"
33
34 namespace v8 {
35 namespace internal {
36
37
38 AsmTyper::AsmTyper(CompilationInfo* info) : info_(info), valid_(true) {
39 InitializeAstVisitor(info->isolate(), info->zone());
40 }
41
42
43 bool AsmTyper::Run(CompilationInfo* info) {
44 AsmTyper* visitor = new(info->zone()) AsmTyper(info);
45 visitor->VisitAsmModule(info->function());
46 #ifdef DEBUG
47 if (FLAG_print_asm_env && visitor->valid_ && !visitor->HasStackOverflow())
48 info->scope()->Print();
49 #endif
50 return visitor->valid_ && !visitor->HasStackOverflow();
51 }
52
53
54 #define RECURSE(call) \
55 do { \
56 DCHECK(valid_ && !HasStackOverflow()); \
57 call; \
58 if (!valid_ || HasStackOverflow()) return; \
59 } while (false)
60
61 #define RECURSE_STMT(stmt) RECURSE(Visit(stmt))
62
63 #ifdef DEBUG
64 #define PRINT_TYPE(label, type) { PrintF("%s", label); type->TypePrint(); }
65 #else
66 #define PRINT_TYPE(label, type) {}
67 #endif
68
69 #define RECURSE_EXPR(expr, expected_type, msg) \
70 do { \
71 Handle<Type> save = expected_type_; \
72 expected_type_ = handle_type(expected_type); \
73 RECURSE(Visit(expr)); \
74 Handle<Type> bounded_type = handle_type( \
75 Type::Intersect(computed_type_, expected_type_)); \
76 if (bounded_type->Is(Type::None())) { \
77 PRINT_TYPE("Computed type: ", computed_type_); \
78 PRINT_TYPE("Expected type: ", expected_type_); \
79 } \
80 if (bounded_type->Is(Type::None())) FAIL(expr, msg); \
81 expected_type_ = save; \
82 } while (false)
83
84 #define RETURN(expr, type) \
85 do { \
86 computed_type_ = handle_type(type); \
87 Handle<Type> bounded_type = handle_type( \
88 Type::Intersect(computed_type_, expected_type_)); \
89 expr->set_bounds(Bounds(bounded_type)); \
90 return; \
91 } while (false)
92
93 #define RETURN_ANNOT(expr, type) \
94 do { \
95 computed_type_ = handle_type(type); \
96 expr->set_bounds(Bounds(computed_type_)); \
97 return; \
98 } while (false)
99
100 #define FAIL(node, msg) \
101 do { \
102 valid_ = false; \
103 int line = node->position() == RelocInfo::kNoPosition \
104 ? -1 : GetScriptLineNumberSafe(info_->script(), node->position()); \
105 PrintF("asm: line %d: %s\n", line, msg); \
106 return; \
107 } while (false)
108
109
110
111 void AsmTyper::VisitAsmModule(FunctionLiteral* fun) {
112 Scope* scope = fun->scope();
113 DCHECK(scope->asm_mode() == ASM_MODULE);
114 DCHECK(scope->is_function_scope());
115
116 // Module parameters.
117 for (int i = 0; i < scope->num_parameters(); ++i) {
118 Variable* param = scope->parameter(i);
119 DCHECK(param->type().is_null());
120 switch (i) {
121 case 0: // stdlib
122 param->set_type(StdlibType());
123 break;
124 case 1: // foreign
125 param->set_type(handle_type(Type::Object()));
126 break;
127 case 2: // heap
128 // TODO(bradnelson): Fix me
129 // param->set_type(handle_type(Type::Buffer()));
130 param->set_type(handle_type(Type::Object()));
131 break;
132 default:
133 param->set_type(handle_type(Type::Any()));
134 }
135 }
136
137 // Declarations.
138 VariableDeclaration* decl = scope->function();
139 if (decl != NULL)
140 decl->proxy()->var()->set_type(handle_type(Type::Function()));
141 RECURSE(VisitDeclarations(scope->declarations()));
142
143 // Body.
144 return_type_ = handle_type(Type::Object());
145 RECURSE(VisitStatements(fun->body()));
146
147 /*
148 // Global variables.
149 ZoneList<Statement*>* stmts = fun->body();
150 bool good = true;
151 int i;
152 for (i = 0; i < stmts->length() - 1; ++i) {
153 good = false;
154 ExpressionStatement* stmt = stmts->at(i)->AsExpressionStatement();
155 if (stmt == NULL) break;
156 Assignment* expr = stmt->expression()->AsAssignment();
157 if (expr == NULL || expr->is_compound()) break;
158 VariableProxy* proxy = expr->target()->AsVariableProxy();
159 if (proxy == NULL) break;
160 Variable* var = proxy->var();
161 if (var->location() != Variable::PARAMETER) {
162 DCHECK(var->type().is_null());
163 RECURSE(VisitExpressionAnnotation(expr->value()));
164 var->set_type(computed_type_);
165 }
166 good = true;
167 }
168 if (!good) FAIL(stmts->at(i), "invalid statement in module body");
169
170 // Export.
171 */
172
173 // Function bodies.
174 ZoneList<Declaration*>* decls = scope->declarations();
175 for (int i = 0; i < decls->length(); ++i) {
176 FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration();
177 if (decl != NULL) {
178 RECURSE_EXPR(decl->fun(), Type::Function(),
179 "function literal expected to be a function");
180 }
181 }
182 }
183
184
185 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) {
186 Variable* var = decl->proxy()->var();
187 if (var->location() != Variable::PARAMETER) {
188 DCHECK(var->type().is_null());
189 var->set_type(handle_type(Type::Any()));
190 }
191 DCHECK(!var->type().is_null());
192 }
193
194
195 void AsmTyper::VisitFunctionDeclaration(FunctionDeclaration* decl) {
196 Variable* var = decl->proxy()->var();
197 DCHECK(var->type().is_null());
198 RECURSE(VisitFunctionAnnotation(decl->fun()));
199 var->set_type(computed_type_);
200 }
201
202
203 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) {
204 DCHECK(fun->scope()->asm_mode() == ASM_FUNCTION);
205
206 // Extract result type.
207 ZoneList<Statement*>* body = fun->body();
208 Handle<Type> result_type = handle_type(Type::Undefined());
209 if (body->length() > 0) {
210 ReturnStatement* stmt = body->last()->AsReturnStatement();
211 if (stmt != NULL) {
212 RECURSE(VisitExpressionAnnotation(stmt->expression()));
213 result_type = computed_type_;
214 }
215 }
216 Handle<FunctionType> type =
217 Type::Function(fun->parameter_count(), result_type, isolate_);
218
219 // Extract parameter types.
220 bool good = true;
221 for (int i = 0; i < fun->parameter_count(); ++i) {
222 good = false;
223 if (i >= body->length()) break;
224 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement();
225 if (stmt == NULL) break;
226 Assignment* expr = stmt->expression()->AsAssignment();
227 if (expr == NULL || expr->is_compound()) break;
228 VariableProxy* proxy = expr->target()->AsVariableProxy();
229 if (proxy == NULL) break;
230 Variable* var = proxy->var();
231 if (var->location() != Variable::PARAMETER || var->index() != i) break;
232 RECURSE(VisitExpressionAnnotation(expr->value()));
233 var->set_type(computed_type_);
234 type->InitParameter(i, computed_type_);
235 good = true;
236 }
237 if (!good) FAIL(fun, "missing parameter type annotations");
238
239 // Set type of function variable if present.
240 VariableDeclaration* decl = fun->scope()->function();
241 if (decl != NULL) decl->proxy()->var()->set_type(type);
242
243 RETURN_ANNOT(fun, type);
244 }
245
246
247 void AsmTyper::VisitExpressionAnnotation(Expression* expr) {
248 // Normal +x or x|0 annotations.
249 BinaryOperation* bin = expr->AsBinaryOperation();
250 if (bin != NULL) {
251 Handle<Type> type;
252 switch (bin->op()) {
253 case Token::MUL: // We encode +x as 1*x
254 RETURN_ANNOT(expr, Type::Double());
255 case Token::BIT_OR:
256 RETURN_ANNOT(expr, Type::Int32());
257 default:
258 FAIL(expr, "invalid type annotation");
259 }
260 }
261
262 // Numbers or the undefined literal (for empty returns).
263 Literal* lit = expr->AsLiteral();
264 if (lit != NULL) {
265 Handle<Object> value = lit->value();
266 if (value->IsSmi())
267 RETURN_ANNOT(expr, Type::Int32());
268 else if (value->IsNumber())
269 RETURN_ANNOT(expr, Type::Double());
270 else if (value->IsUndefined())
271 RETURN_ANNOT(expr, Type::Undefined());
272 else
273 FAIL(expr, "invalid type annotation");
274 }
275 /*
276 // Global stdlib.x, stdlib.Math.x, or foreign.x annotations.
277 Property* prop = expr->AsProperty();
278 if (prop != NULL) {
279 // Get property name.
280 Literal* key = prop->key()->AsLiteral();
281 if (key == NULL || !key->IsPropertyName())
282 FAIL(expr, "invalid type annotation");
283 Handle<String> name = key->AsPropertyName();
284
285 // stdlib.x or foreign.x
286 VariableProxy* proxy = prop->obj()->AsVariableProxy();
287 if (proxy != NULL) {
288 Variable* var = proxy->var();
289 if (var->location() != Variable::PARAMETER)
290 FAIL(expr, "invalid type annotation");
291 switch (var->index()) {
292 case 0: {
293 // Object is stdlib, look up library type.
294 Handle<Type> type = LibType(global_lib_, name);
295 if (type.is_null()) FAIL(expr, "unknown standard function");
296 RETURN_ANNOT(expr, type);
297 }
298 case 1:
299 // Object is foreign lib.
300 RETURN_ANNOT(expr, Type::Function());
301 default:
302 FAIL(expr, "invalid type annotation");
303 }
304 }
305
306 // stdlib.Math.x
307 Property* inner_prop = prop->obj()->AsProperty();
308 if (inner_prop != NULL) {
309 // Check that inner property name is "Math".
310 Literal* math_key = inner_prop->key()->AsLiteral();
311 if (math_key == NULL || !math_key->IsPropertyName() ||
312 !math_key->AsPropertyName()->IsUtf8EqualTo(CStrVector("Math")))
313 FAIL(expr, "invalid type annotation");
314
315 // Check that object is stdlib.
316 VariableProxy* proxy = prop->obj()->AsVariableProxy();
317 if (proxy == NULL) FAIL(expr, "invalid type annotation");
318 Variable* var = proxy->var();
319 if (var->location() != Variable::PARAMETER || var->index() != 0)
320 FAIL(expr, "invalid type annotation");
321
322 // Look up library type.
323 Handle<Type> type = LibType(math_lib_, name);
324 if (type.is_null()) FAIL(expr, "unknown standard function");
325 RETURN_ANNOT(expr, type);
326 }
327 }
328
329 // Global heap view annotation.
330 CallNew* cons = expr->AsCallNew();
331 if (cons != NULL && cons->arguments()->length() == 1) {
332 // Check that argument is heap parameter.
333 VariableProxy* arg = cons->arguments()->at(0)->AsVariableProxy();
334 if (arg == NULL) FAIL(expr, "invalid type annotation");
335 Variable* heap_var = arg->var();
336 if (heap_var->location() != Variable::PARAMETER || heap_var->index() != 2)
337 FAIL(expr, "invalid type annotation");
338
339 Property* prop = cons->expression()->AsProperty();
340 if (prop == NULL) FAIL(expr, "invalid type annotation");
341
342 // Check that object is stdlib.
343 VariableProxy* proxy = prop->obj()->AsVariableProxy();
344 if (proxy == NULL) FAIL(expr, "invalid type annotation");
345 Variable* lib_var = proxy->var();
346 if (lib_var->location() != Variable::PARAMETER || lib_var->index() != 0)
347 FAIL(expr, "invalid type annotation");
348
349 // Look up array type.
350 Literal* key = prop->key()->AsLiteral();
351 if (key == NULL || !key->IsPropertyName())
352 FAIL(expr, "invalid type annotation");
353 Handle<String> name = key->AsPropertyName();
354 Handle<Type> type = LibType(array_lib_, name);
355 if (type.is_null()) FAIL(expr, "unknown array view");
356 RETURN_ANNOT(expr, type);
357 }
358
359 // Function table.
360 ArrayLiteral* array = expr->AsArrayLiteral();
361 if (array != NULL && array->values()->length() > 0) {
362 ZoneList<Expression*>* values = array->values();
363 Handle<Type> type(Type::None(), isolate_);
364 for (int i = 0; i < values->length(); ++i) {
365 // Check that value is a variable.
366 VariableProxy* proxy = values->at(i)->AsVariableProxy();
367 if (proxy == NULL) FAIL(expr, "invalid entry in function table");
368
369 // Merge type.
370 Handle<Type> type_i = proxy->var()->type();
371 if (type_i.is_null() || !type_i->IsFunction())
372 FAIL(proxy, "invalid entry in function table");
373 type = handle(Type::Union(type, type_i), isolate_);
374 }
375 RETURN_ANNOT(expr, Type::Array(type, isolate_));
376 }
377 */
378 FAIL(expr, "invalid type annotation");
379 }
380
381
382 void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) {
383 for (int i = 0; i < stmts->length(); ++i) {
384 Statement* stmt = stmts->at(i);
385 RECURSE_STMT(stmt);
386 }
387 }
388
389
390 void AsmTyper::VisitBlock(Block* stmt) {
391 RECURSE(VisitStatements(stmt->statements()));
392 }
393
394
395 void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
396 RECURSE_EXPR(stmt->expression(), Type::Any(),
397 "expression statement expected to ba any");
398 }
399
400
401 void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {
402 }
403
404
405 void AsmTyper::VisitIfStatement(IfStatement* stmt) {
406 RECURSE_EXPR(stmt->condition(), Type::Int32(),
407 "if condition expected to be integer");
408 RECURSE_STMT(stmt->then_statement());
409 RECURSE_STMT(stmt->else_statement());
410 }
411
412
413 void AsmTyper::VisitContinueStatement(ContinueStatement* stmt) {
414 }
415
416
417 void AsmTyper::VisitBreakStatement(BreakStatement* stmt) {
418 }
419
420
421 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) {
422 RECURSE_EXPR(stmt->expression(), return_type_,
423 "return expression expected to have return type");
424 }
425
426
427 void AsmTyper::VisitWithStatement(WithStatement* stmt) {
428 FAIL(stmt, "with statement encountered");
429 }
430
431
432 void AsmTyper::VisitSwitchStatement(SwitchStatement* stmt) {
433 RECURSE_EXPR(stmt->tag(), Type::Signed32(),
434 "switch expression expected to be integer");
435
436 ZoneList<CaseClause*>* clauses = stmt->cases();
437 SwitchStatement::SwitchType switch_type = SwitchStatement::SMI_SWITCH;
438 for (int i = 0; i < clauses->length(); ++i) {
439 CaseClause* clause = clauses->at(i);
440 if (!clause->is_default()) {
441 Expression* label = clause->label();
442 RECURSE_EXPR(label, Type::Signed32(),
443 "case label expected to be integer");
444 if (!label->IsLiteral()) FAIL(label, "illegal label");
445 Handle<Object> value = label->AsLiteral()->value();
446 if (!value->IsSmi()) {
447 if (!value->IsHeapNumber()) FAIL(label, "illegal label");
448 double x = HeapNumber::cast(*value)->value();
449 if (static_cast<int32_t>(x) != x) FAIL(label, "illegal label");
450 // TODO(rossberg): we'd need a SIGNED32_SWITCH to be precise.
451 switch_type = SwitchStatement::GENERIC_SWITCH;
452 }
453 }
454 ZoneList<Statement*>* stmts = clause->statements();
455 RECURSE(VisitStatements(stmts));
456 }
457 stmt->set_switch_type(switch_type);
458 }
459
460
461 void AsmTyper::VisitCaseClause(CaseClause* clause) {
462 UNREACHABLE();
463 }
464
465
466 void AsmTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
467 RECURSE_STMT(stmt->body());
468 RECURSE_EXPR(stmt->cond(), Type::Int32(),
469 "do condition expected to be integer");
470 }
471
472
473 void AsmTyper::VisitWhileStatement(WhileStatement* stmt) {
474 RECURSE_EXPR(stmt->cond(), Type::Int32(),
475 "while condition expected to be integer");
476 RECURSE_STMT(stmt->body());
477 }
478
479
480 void AsmTyper::VisitForStatement(ForStatement* stmt) {
481 if (stmt->init() != NULL) RECURSE_STMT(stmt->init());
482 if (stmt->cond() != NULL) RECURSE_EXPR(stmt->cond(), Type::Int32(),
483 "for condition expected to be integer");
484 if (stmt->next() != NULL) RECURSE_STMT(stmt->next());
485 RECURSE_STMT(stmt->body());
486 }
487
488
489 void AsmTyper::VisitForInStatement(ForInStatement* stmt) {
490 FAIL(stmt, "for-in statement encountered");
491 }
492
493
494 void AsmTyper::VisitForOfStatement(ForOfStatement* stmt) {
495 FAIL(stmt, "for-of statement encountered");
496 }
497
498
499 void AsmTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
500 FAIL(stmt, "try statement encountered");
501 }
502
503
504 void AsmTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
505 FAIL(stmt, "try statement encountered");
506 }
507
508
509 void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
510 FAIL(stmt, "debugger statement encountered");
511 }
512
513
514 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
515 Scope* scope = expr->scope();
516 DCHECK(scope->is_function_scope());
517 DCHECK(scope->asm_mode() == ASM_FUNCTION);
518
519 if (!expr->bounds().upper->IsFunction())
520 FAIL(expr, "invalid function literal");
521
522 Handle<FunctionType> type(expr->bounds().upper->AsFunction());
523 Handle<Type> save_return_type = return_type_;
524 return_type_ = type->Result();
525 RECURSE(VisitDeclarations(scope->declarations()));
526 RECURSE(VisitStatements(expr->body()));
527 return_type_ = save_return_type;
528 RETURN(expr, type);
529 }
530
531
532 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
533 FAIL(expr, "function info literal encountered");
534 }
535
536
537 void AsmTyper::VisitConditional(Conditional* expr) {
538 RECURSE_EXPR(expr->condition(), Type::Int32(),
539 "condition expected to be integer");
540 RECURSE_EXPR(expr->then_expression(), Type::Number(),
541 "conditional then branch expected to be integer");
542 Handle<Type> then_type = computed_type_;
543 RECURSE_EXPR(expr->else_expression(), Type::Number(),
544 "conditional else branch expected to be integer");
545 Handle<Type> else_type = computed_type_;
546 Handle<Type> type = handle_type(Type::Intersect(then_type, else_type));
547 if (!(type->Is(Type::Int32()) || type->Is(Type::Double())))
548 FAIL(expr, "ill-typed conditional");
549 RETURN(expr, type);
550 }
551
552
553 void AsmTyper::VisitVariableProxy(VariableProxy* expr) {
554 Variable* var = expr->var();
555 if (var->type().is_null()) FAIL(expr, "unbound variable");
556 Handle<Type> type = handle_type(Type::Intersect(var->type(), expected_type_));
557 if (type->Is(Type::Int32())) type = handle_type(Type::Int32());
558 var->set_type(type);
559 RETURN(expr, type);
560 }
561
562
563 void AsmTyper::VisitLiteral(Literal* expr) {
564 Handle<Object> value = expr->value();
565 if (value->IsNumber()) {
566 int32_t i;
567 uint32_t u;
568 if (expr->is_float())
569 RETURN(expr, Type::Double());
570 else if (value->ToUint32(&u))
571 RETURN(expr, u < 0x80000000u ? Type::Unsigned31() : Type::Unsigned32());
572 else if (value->ToInt32(&i))
573 RETURN(expr, Type::Signed32());
574 else
575 FAIL(expr, "illegal number");
576 } else if (value->IsString()) {
577 RETURN(expr, Type::String());
578 } else if (value->IsUndefined()) {
579 RETURN(expr, Type::Undefined());
580 } else {
581 FAIL(expr, "illegal literal");
582 }
583 }
584
585
586 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
587 FAIL(expr, "regular expression encountered");
588 }
589
590
591 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) {
592 // Allowed for asm module's export declaration.
593 ZoneList<ObjectLiteralProperty*>* props = expr->properties();
594 Handle<ObjectType> type = Type::Object(props->length(), isolate_);
595 for (int i = 0; i < props->length(); ++i) {
596 ObjectLiteralProperty* prop = props->at(i);
597 RECURSE_EXPR(prop->value(), Type::Function(),
598 "object property expected to be a function");
599 type->InitProperty(i, prop->key()->AsPropertyName(), computed_type_);
600 }
601 RETURN(expr, type);
602 }
603
604
605 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) {
606 // Allowed for function tables.
607 ZoneList<Expression*>* values = expr->values();
608 Handle<Type> elem_type = handle_type(Type::None());
609 for (int i = 0; i < values->length(); ++i) {
610 Expression* value = values->at(i);
611 RECURSE_EXPR(value, Type::Function(),
612 "array component expected to be a function");
613 elem_type = handle_type(Type::Union(elem_type, computed_type_));
614 }
615 RETURN(expr, Type::Array(elem_type, isolate_));
616 }
617
618
619 void AsmTyper::VisitAssignment(Assignment* expr) {
620 if (expr->is_compound()) FAIL(expr, "compound assignment encountered");
621 RECURSE_EXPR(expr->value(), expected_type_,
622 "assignment value expected to match surrounding");
623 RECURSE_EXPR(expr->target(), computed_type_,
624 "assignment target expected to match value");
625 RETURN(expr, computed_type_);
626 }
627
628
629 void AsmTyper::VisitYield(Yield* expr) {
630 FAIL(expr, "yield expression encountered");
631 }
632
633
634 void AsmTyper::VisitThrow(Throw* expr) {
635 FAIL(expr, "throw statement encountered");
636 }
637
638
639 void AsmTyper::VisitProperty(Property* expr) {
640 RECURSE_EXPR(expr->obj(), Type::Object(),
641 "property holder expected to be object");
642
643 // For heap or function table access.
644 if (computed_type_->IsArray()) {
645 Handle<ArrayType> array_type = Handle<ArrayType>::cast(computed_type_);
646 RECURSE_EXPR(expr->key(), Type::Unsigned32(),
647 "array index expected to be unsigned integer");
648 Handle<Type> type = array_type->AsArray()->Element();
649 if (type->Is(Type::Int32()))
650 RETURN(expr, Type::Int32());
651 else if (type->Is(Type::Double()))
652 RETURN(expr, Type::Double());
653 else
654 RETURN(expr, type);
655 }
656
657 // For stdlib access.
658 if (computed_type_->IsObject() && expr->key()->IsPropertyName()) {
659 Handle<ObjectType> object_type = Handle<ObjectType>::cast(computed_type_);
660 RECURSE_EXPR(expr->key(), Type::Name(),
661 "stdlib name expected to be name");
662 RETURN(expr,
663 object_type->Property(expr->key()->AsLiteral()->AsPropertyName()));
664 }
665
666 // For foreign or other accesses.
667 RECURSE_EXPR(expr->key(), Type::Any(),
668 "foreign index expected to be any");
669 RETURN(expr, Type::Any());
670 }
671
672
673 void AsmTyper::VisitCall(Call* expr) {
674 RECURSE_EXPR(expr->expression(), Type::Function(),
675 "callee expected to be function");
676 if (computed_type_->IsFunction()) {
677 Handle<FunctionType> fun_type = Handle<FunctionType>::cast(computed_type_);
678 ZoneList<Expression*>* args = expr->arguments();
679 if (fun_type->Arity() != args->length())
680 FAIL(expr, "call with wrong arity");
681 for (int i = 0; i < args->length(); ++i) {
682 Expression* arg = args->at(i);
683 RECURSE_EXPR(arg, fun_type->Parameter(i),
684 "call argument expected to match callee parameter");
685 }
686 RETURN(expr, fun_type->Result());
687 } else {
688 // For foreign calls.
689 ZoneList<Expression*>* args = expr->arguments();
690 for (int i = 0; i < args->length(); ++i) {
691 Expression* arg = args->at(i);
692 RECURSE_EXPR(arg, Type::Any(),
693 "foreign call argument expected to be any");
694 }
695 RETURN(expr, Type::Number());
696 }
697 }
698
699
700 void AsmTyper::VisitCallNew(CallNew* expr) {
701 RECURSE_EXPR(expr->expression(), Type::Function(),
702 "constructor expected to be function");
703 if (computed_type_->IsFunction()) {
704 Handle<FunctionType> fun_type = Handle<FunctionType>::cast(computed_type_);
705 ZoneList<Expression*>* args = expr->arguments();
706 if (fun_type->Arity() != args->length())
707 FAIL(expr, "call with wrong arity");
708 for (int i = 0; i < args->length(); ++i) {
709 Expression* arg = args->at(i);
710 RECURSE_EXPR(arg, fun_type->Parameter(i),
711 "constructor argument expected to match callee parameter");
712 }
713 RETURN(expr, fun_type->Result());
714 }
715
716 FAIL(expr, "ill-typed new operator");
717 }
718
719
720 void AsmTyper::VisitCallRuntime(CallRuntime* expr) {
721 FAIL(expr, "runtime call encountered");
722 }
723
724
725 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) {
726 switch (expr->op()) {
727 case Token::NOT: // Used to encode != and !==
728 RECURSE_EXPR(expr->expression(), Type::Int32(),
729 "operand expected to be integer");
730 RETURN(expr, Type::Int32());
731 case Token::DELETE:
732 FAIL(expr, "delete operator encountered");
733 case Token::VOID:
734 FAIL(expr, "void operator encountered");
735 case Token::TYPEOF:
736 FAIL(expr, "typeof operator encountered");
737 default:
738 UNREACHABLE();
739 }
740 }
741
742
743 void AsmTyper::VisitCountOperation(CountOperation* expr) {
744 FAIL(expr, "increment or decrement operator encountered");
745 }
746
747
748 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
749 // TODO(rossberg): recognise unary +, -, ~ and ~~.
750 switch (expr->op()) {
751 case Token::COMMA: {
752 RECURSE_EXPR(expr->left(), Type::Any(),
753 "left comma operand expected to be any");
754 RECURSE_EXPR(expr->right(), Type::Any(),
755 "right comma operand expected to be any");
756 RETURN(expr, computed_type_);
757 }
758 case Token::OR:
759 case Token::AND:
760 FAIL(expr, "logical operator encountered");
761 case Token::BIT_OR:
762 case Token::BIT_AND:
763 case Token::BIT_XOR:
764 case Token::SHL:
765 case Token::SHR:
766 case Token::SAR: {
767 // BIT_OR allows Any since it is used as a type coercion.
768 // BIT_XOR allows Number since it is used as a type coercion (encoding ~).
769 Type* expectation =
770 expr->op() == Token::BIT_OR ? Type::Any() :
771 expr->op() == Token::BIT_XOR ? Type::Number() : Type::Int32();
772 Type* result =
773 expr->op() == Token::SHR ? Type::Unsigned32() : Type::Signed32();
774 RECURSE_EXPR(expr->left(), expectation,
775 "left bit operand expected to be integer");
776 RECURSE_EXPR(expr->right(), expectation,
777 "right bit operand expected to be integer");
778 RETURN(expr, result);
779 }
780 case Token::ADD:
781 case Token::SUB:
782 case Token::MUL:
783 case Token::DIV:
784 case Token::MOD: {
785 // MUL allows Any, since it is used as a type coercion (encoding unary +).
786 Type* expectation =
787 expr->op() == Token::MUL ? Type::Any() : Type::Number();
788 RECURSE_EXPR(expr->left(), expectation,
789 "left arithmetic operand expected to be number");
790 Handle<Type> left_type = computed_type_;
791 RECURSE_EXPR(expr->right(), expectation,
792 "right arithmetic operand expected to be number");
793 Handle<Type> right_type = computed_type_;
794 Handle<Type> type = handle_type(Type::Intersect(left_type, right_type));
795 if (type->Is(Type::Int32()))
796 RETURN(expr, Type::Int32());
797 else if (type->Is(Type::Number()))
798 RETURN(expr, Type::Double());
799 else
800 FAIL(expr, "ill-typed arithmetic operation");
801 }
802 default:
803 UNREACHABLE();
804 }
805 }
806
807
808 void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
809 RECURSE_EXPR(expr->left(), Type::Number(),
810 "left comparison operand expected to be number");
811 Handle<Type> left_type = computed_type_;
812 RECURSE_EXPR(expr->right(), Type::Number(),
813 "right comparison operand expected to be number");
814 Handle<Type> right_type = computed_type_;
815 Handle<Type> type = handle_type(Type::Union(left_type, right_type));
816 expr->set_combined_type(type);
817 if (type->Is(Type::Int32()) || type->Is(Type::Double()))
818 RETURN(expr, Type::Int32());
819 else
820 FAIL(expr, "ill-typed comparison operation");
821 }
822
823
824 void AsmTyper::VisitThisFunction(ThisFunction* expr) {
825 RETURN(expr, Type::Function());
826 }
827
828
829 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
830 for (int i = 0; i < decls->length(); ++i) {
831 Declaration* decl = decls->at(i);
832 RECURSE_STMT(decl);
833 }
834 }
835
836
837 void AsmTyper::VisitModuleDeclaration(ModuleDeclaration* decl) {
838 FAIL(decl, "module declaration encountered");
839 }
840
841
842 void AsmTyper::VisitImportDeclaration(ImportDeclaration* decl) {
843 FAIL(decl, "import declaration encountered");
844 }
845
846
847 void AsmTyper::VisitExportDeclaration(ExportDeclaration* decl) {
848 FAIL(decl, "export declaration encountered");
849 }
850
851
852 void AsmTyper::VisitModuleLiteral(ModuleLiteral* module) {
853 FAIL(module, "module encountered");
854 }
855
856
857 void AsmTyper::VisitModuleVariable(ModuleVariable* module) {
858 FAIL(module, "module encountered");
859 }
860
861
862 void AsmTyper::VisitModulePath(ModulePath* module) {
863 FAIL(module, "module encountered");
864 }
865
866
867 void AsmTyper::VisitModuleUrl(ModuleUrl* module) {
868 FAIL(module, "module encountered");
869 }
870
871
872 void AsmTyper::VisitModuleStatement(ModuleStatement* stmt) {
873 FAIL(stmt, "module encountered");
874 }
875
876
877 Handle<Type> AsmTyper::StdlibType() {
878 Handle<Type> no_type;
879 Handle<Type> signed8_type = handle_type(Type::Signed8());
880 Handle<Type> unsigned8_type = handle_type(Type::Unsigned8());
881 Handle<Type> signed16_type = handle_type(Type::Signed16());
882 Handle<Type> unsigned16_type = handle_type(Type::Unsigned16());
883 Handle<Type> signed32_type = handle_type(Type::Signed32());
884 Handle<Type> unsigned32_type = handle_type(Type::Unsigned32());
885 Handle<Type> int32_type = handle_type(Type::Int32());
886 Handle<Type> float32_type = handle_type(Type::Float32());
887 Handle<Type> double_type = handle_type(Type::Double());
888 Handle<Type> number_type = handle_type(Type::Number());
889
890 Handle<FunctionType> double_fn1_type =
891 Type::Function(double_type, double_type, isolate_);
892 Handle<FunctionType> double_fn2_type =
893 Type::Function(double_type, double_type, double_type, isolate_);
894
895 Handle<FunctionType> imul_type =
896 Type::Function(int32_type, int32_type, signed32_type, isolate_);
897 // TODO(rossberg): currently only approximating the proper intersection type
898 // (which we cannot currently represent).
899 Handle<FunctionType> abs_type =
900 Type::Function(number_type, number_type, isolate_);
901
902 struct Assignment {
903 const char* name;
904 Handle<Type> type;
905 };
906
907 const Assignment math[] = {
908 {"PI", double_type},
909 {"E", double_type},
910 {"LN2", double_type},
911 {"LN10", double_type},
912 {"LOG2E", double_type},
913 {"LOG10E", double_type},
914 {"SQRT2", double_type},
915 {"SQRT1_2", double_type},
916 {"imul", imul_type},
917 {"abs", abs_type},
918 {"ceil", double_fn1_type},
919 {"floor", double_fn1_type},
920 {"pow", double_fn2_type},
921 {"exp", double_fn1_type},
922 {"log", double_fn1_type},
923 {"sqrt", double_fn1_type},
924 {"cos", double_fn1_type},
925 {"sin", double_fn1_type},
926 {"tan", double_fn1_type},
927 {"acos", double_fn1_type},
928 {"asin", double_fn1_type},
929 {"atan", double_fn1_type},
930 {"atan2", double_fn2_type}
931 };
932 Handle<ObjectType> math_type = Type::Object(ARRAY_SIZE(math), isolate_);
933 for (unsigned i = 0; i < ARRAY_SIZE(math); ++i) {
934 math_type->InitProperty(i,
935 isolate_->factory()->InternalizeUtf8String(math[i].name), math[i].type);
936 }
937
938 Handle<Type> buffer_type = handle_type(Type::Buffer());
939 Handle<ArrayType> int8_array_type = Type::Array(signed8_type, isolate_);
940 Handle<ArrayType> uint8_array_type = Type::Array(unsigned8_type, isolate_);
941 Handle<ArrayType> int16_array_type = Type::Array(signed16_type, isolate_);
942 Handle<ArrayType> uint16_array_type = Type::Array(unsigned16_type, isolate_);
943 Handle<ArrayType> int32_array_type = Type::Array(signed32_type, isolate_);
944 Handle<ArrayType> uint32_array_type = Type::Array(unsigned32_type, isolate_);
945 Handle<ArrayType> float32_array_type = Type::Array(float32_type, isolate_);
946 Handle<ArrayType> float64_array_type = Type::Array(double_type, isolate_);
947
948 Handle<FunctionType> int8_array_cons_type =
949 Type::Function(buffer_type, int8_array_type, isolate_);
950 Handle<FunctionType> uint8_array_cons_type =
951 Type::Function(buffer_type, uint8_array_type, isolate_);
952 Handle<FunctionType> int16_array_cons_type =
953 Type::Function(buffer_type, int16_array_type, isolate_);
954 Handle<FunctionType> uint16_array_cons_type =
955 Type::Function(buffer_type, uint16_array_type, isolate_);
956 Handle<FunctionType> int32_array_cons_type =
957 Type::Function(buffer_type, int32_array_type, isolate_);
958 Handle<FunctionType> uint32_array_cons_type =
959 Type::Function(buffer_type, uint32_array_type, isolate_);
960 Handle<FunctionType> float32_array_cons_type =
961 Type::Function(buffer_type, float32_array_type, isolate_);
962 Handle<FunctionType> float64_array_cons_type =
963 Type::Function(buffer_type, float64_array_type, isolate_);
964
965 const Assignment global[] = {
966 {"Infinity", double_type},
967 {"NaN", double_type},
968 {"Math", math_type},
969 {"Int8Array", int8_array_cons_type},
970 {"Uint8Array", uint8_array_cons_type},
971 {"Int16Array", int16_array_cons_type},
972 {"Uint16Array", uint16_array_cons_type},
973 {"Int32Array", int32_array_cons_type},
974 {"Uint32Array", uint32_array_cons_type},
975 {"Float32Array", float32_array_cons_type},
976 {"Float64Array", float64_array_cons_type}
977 };
978 Handle<ObjectType> global_type = Type::Object(ARRAY_SIZE(global), isolate_);
979 for (unsigned i = 0; i < ARRAY_SIZE(global); ++i) {
980 global_type->InitProperty(i,
981 isolate_->factory()->InternalizeUtf8String(global[i].name),
982 global[i].type);
983 }
984
985 return global_type;
986 }
987
988 } } // namespace v8::internal
989
990 #endif
OLDNEW
« no previous file with comments | « src/typing-asm.h ('k') | src/variables.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698