src/compiler/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Sat Dec 22 19:48:43 2012 -0800 (2012-12-22)
changeset 232 2b8512340180
parent 230 fb3cd08bc7fb
child 233 bbb498ccb4ac
permissions -rw-r--r--
Re-introduce definite return analysis.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of SourcePawn.
     6  *
     7  * SourcePawn is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * SourcePawn. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include <assert.h>
    20 #include "../Zone.h"
    21 #include "../Strings.h"
    22 #include "../NativeTable.h"
    23 #include "../TypeManager.h"
    24 #include "../Modules.h"
    25 #include "../Code.h"
    26 #include "SemanticAnalysis.h"
    27 #include "../Heap-inl.h"
    28 
    29 using namespace ke;
    30 
    31 #define __ emitter_.
    32 
    33 typedef BytecodeEmitter::Label Label;
    34 
    35 class AutoEnterScope
    36 {
    37   public:
    38     AutoEnterScope(Scope **prevp, Scope *scope)
    39       : prevp_(prevp),
    40         prev_(*prevp),
    41         scope_(scope)
    42     {
    43         if (!scope_)
    44             return;
    45         prev_ = *prevp_;
    46         *prevp_ = scope;
    47         assert(prev_ == scope->enclosing());
    48     }
    49     ~AutoEnterScope()
    50     {
    51         if (scope_)
    52             *prevp_ = prev_;
    53     }
    54   private:
    55     Scope **prevp_;
    56     Scope *prev_;
    57     Scope *scope_;
    58 };
    59 
    60 SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, TranslationUnit *unit)
    61   : zone_(zone),
    62     pool_(zone->pool()),
    63     cc_(cc),
    64     unit_(unit),
    65     hir_(NULL),
    66     emitter_(pool_),
    67     module_(NULL),
    68     loop_(NULL)
    69 {
    70 }
    71 
    72 SemanticAnalysis::SemanticAnalysis(SemanticAnalysis *parent, Handle<FunctionType> fun)
    73   : zone_(parent->zone_),
    74     pool_(parent->pool_),
    75     cc_(parent->cc_),
    76     unit_(parent->unit_),
    77     hir_(NULL),
    78     scope_(parent->scope_),
    79     emitter_(pool_),
    80     module_(parent->module_),
    81     fun_(fun),
    82     loop_(NULL),
    83     control_(NULL)
    84 {
    85 
    86 }
    87 
    88 void
    89 SemanticAnalysis::analyze()
    90 {
    91     scope_ = unit_->globalScope();
    92 
    93     module_ = Module::New(zone_);
    94 
    95     for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
    96         Statement *stmt = unit_->tree()->statements()->at(i);
    97         stmt->accept(this);
    98     }
    99 
   100     Local<Struct> globals(zone_, unit_->globalScope()->build(zone_));
   101     if (!globals)
   102         return;
   103     module_->setGlobals(globals);
   104 
   105     Local<Code> code(zone_, __ finish());
   106     if (!code)
   107         return;
   108     code->setModule(module_);
   109     module_->setCode(code);
   110 
   111 #ifndef NDEBUG
   112 //    Disassemble(code, stdout);
   113 #endif
   114 
   115     unit_->module_ = module_;
   116 }
   117 
   118 void
   119 SemanticAnalysis::visitFunctionStatement(FunctionStatement *stmt)
   120 {
   121     FunctionSymbol *sym = stmt->sym();
   122     Local<FunctionType> type(zone_, sym->type());
   123 
   124     assert(scope_->kind() == Scope::GLOBAL);
   125 
   126     if (stmt->token() == TOK_NATIVE) {
   127         // Define the native now.
   128         size_t index;
   129         if (!zone_->nativeTable()->add(stmt->name(), &index))
   130             return;
   131 
   132         Local<Native> native(zone_, Native::New(zone_, type, index));
   133         if (!native)
   134             return;
   135 
   136         __ object(native);
   137         __ setglobal(sym);
   138         __ pop();
   139     }
   140 
   141     // If the function is a forward or native, we don't have to do anything.
   142     if (stmt->token() == TOK_NATIVE || stmt->token() == TOK_FORWARD)
   143         return;
   144 
   145     SemanticAnalysis child(this, type);
   146     Local<Function> funobj(zone_, child.compile(stmt));
   147     if (!funobj)
   148         return;
   149 
   150     __ object(funobj);
   151     __ setglobal(sym);
   152     if (stmt->token() == TOK_PUBLIC)
   153         __ public_();
   154     else
   155         __ pop();
   156 }
   157 
   158 Function *
   159 SemanticAnalysis::compile(FunctionStatement *stmt)
   160 {
   161     __ setFirstLine(stmt->pos().line);
   162 
   163     AutoEnterScope argScope(&scope_, stmt->argScope());
   164 
   165     for (size_t i = 0; i < stmt->signature().parameters()->length(); i++) {
   166         Parameter *param = stmt->signature().parameters()->at(i);
   167         param->sym()->allocate(VariableSymbol::Arg, i);
   168     }
   169 
   170     AutoEnterScope varScope(&scope_, stmt->varScope());
   171     ControlStatus status = visitForControl(stmt->body());
   172 
   173     if (!fun_->returnType()->isVoid()) {
   174         // If the function is not void, report if not all paths return a value.
   175         // All other incorrect return cases have been caught already.
   176         if (status.returns() == Returns_Sometimes) {
   177             cc_.reportError(stmt->pos(), Message_NotAllPathsReturnValue);
   178             return NULL;
   179         }
   180 
   181         if (status.returns() == Returns_Never) {
   182             cc_.reportError(stmt->pos(), Message_MissingReturnValue);
   183             return NULL;
   184         }
   185     }
   186 
   187     Local<Code> code(zone_, __ finish());
   188     if (!code)
   189         return NULL;
   190     code->setModule(module_);
   191 
   192     Local<Function> fun(zone_, Function::New(zone_, code, fun_, stmt->name(), stmt->pos()));
   193     if (!fun)
   194         return NULL;
   195 
   196 #ifndef NDEBUG
   197 //    Disassemble(code, stdout);
   198 #endif
   199 
   200     return fun;
   201 }
   202 
   203 void 
   204 SemanticAnalysis::visitBlockStatement(BlockStatement *node)
   205 {
   206     AutoEnterScope scope(&scope_, node->scope());
   207 
   208     for (size_t i = 0; i < node->statements()->length(); i++) {
   209         Statement *stmt = node->statements()->at(i);
   210         __ note_position(stmt->pos());
   211         stmt->accept(this);
   212         assert(__ stackDepth() == 0);
   213     }
   214 }
   215 
   216 void
   217 SemanticAnalysis::visitExpressionStatement(ExpressionStatement *node)
   218 {
   219     // While building HIR, we enter new pool and root scopes, since HIR
   220     // creation is purely temporary.
   221     PoolScope poolScope(zone_->pool());
   222     RootScope rootScope(zone_);
   223 
   224     HIR *hir = eval(node->expression());
   225     if (!hir)
   226         return;
   227 
   228     discharge(hir);
   229     if (!hir->type()->isVoid())
   230         __ pop();
   231 }
   232 
   233 void
   234 SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
   235 {
   236     // If both sides terminate in a return, we consider this a return as well.
   237     if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
   238         terminate(Returns_Always);
   239         return;
   240     }
   241 
   242     ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
   243                           ? Returns_Never
   244                           : Returns_Sometimes;
   245 
   246     if (left.terminates() && right.terminates())
   247         terminate(status);
   248     else
   249         returns(status);
   250 }
   251 
   252 SemanticAnalysis::ControlStatus
   253 SemanticAnalysis::visitForControl(Statement *statement)
   254 {
   255     ControlScope scope(&control_);
   256     statement->accept(this);
   257     return scope.status();
   258 }
   259 
   260 void
   261 SemanticAnalysis::visitIfStatement(IfStatement *node)
   262 {
   263     Label join;
   264 
   265     ControlStatus trueBranch;
   266     ControlStatus falseBranch(false, Returns_Never);
   267 
   268     if (!node->ifFalse()) {
   269         Label success;
   270 
   271         visitForTest(node->condition(), &success, &join, &success);
   272         __ bind(&success);
   273         trueBranch = visitForControl(node->ifTrue());
   274     } else {
   275         Label success, next;
   276 
   277         visitForTest(node->condition(), &success, &next, &success);
   278         __ bind(&success);
   279         trueBranch = visitForControl(node->ifTrue());
   280         __ jump(&join);
   281         __ bind(&next);
   282         falseBranch = visitForControl(node->ifFalse());
   283     }
   284 
   285     __ bind(&join);
   286 
   287     control_->merge(trueBranch, falseBranch);
   288 }
   289 
   290 void
   291 SemanticAnalysis::requireLifoStack()
   292 {
   293     if (!loop_)
   294         return;
   295 
   296     loop_->setUsesLifoStack();
   297 }
   298 
   299 SemanticAnalysis::ControlStatus
   300 SemanticAnalysis::visitLoopBody(Statement *stmt)
   301 {
   302     // We always mark off a loop body, so on each edge, we can balance the
   303     // LIFO stack. Right now, we don't have the ability to budget the LIFO
   304     // stack ahead of time. If we turn out to never need the LIFO stack, we
   305     // mark it as unnecessary. (The interpreter can't really make use of this,
   306     // but the JIT can).
   307     //
   308     // Note that balancing the LIFO stack isn't even necessary, so this
   309     // feature may be removed. All this mechanism does is mitigate the
   310     // possibility that a long-running loop will overflow the LIFO region
   311     // and therefore start requiring nursery allocations.
   312     int pos = __ enterloop();
   313     ControlStatus status = visitForControl(stmt);
   314     __ leaveloop();
   315 
   316     if (loop_->usesLifoStack())
   317         __ setLoopUsesLifoStack(pos);
   318 
   319     return status;
   320 }
   321 
   322 void
   323 SemanticAnalysis::visitForStatement(ForStatement *node)
   324 {
   325     AutoEnterScope scope(&scope_, node->scope());
   326     PoolScope poolScope(zone_->pool());
   327     RootScope rootScope(zone_);
   328 
   329     Label join, update;
   330     LoopScope loop(scope_, &join, &update, &loop_);
   331 
   332     if (node->initialization())
   333         node->initialization()->accept(this);
   334 
   335     Label header, test;
   336     if (node->condition())
   337         __ jump(&test);
   338 
   339     __ bind(&header);
   340     ControlStatus status = visitLoopBody(node->body());
   341 
   342     __ bind(&update);
   343     if (node->update())
   344         node->update()->accept(this);
   345 
   346     if (node->condition()) {
   347         __ bind(&test);
   348         visitForTest(node->condition(), &header, &join, &join);
   349     } else {
   350         __ jump(&header);
   351     }
   352 
   353     __ bind(&join);
   354     
   355     // If there was a condition, we treat this like a while loop. Otherwise,
   356     // the join point is only reachable if the loop contains a break. The
   357     // termination status doesn't tell us anything yet.
   358     if (node->condition() || loop.breaks())
   359         control_->merge(status, ControlStatus(false, Returns_Never));
   360     else
   361         control_->terminate(status.returns());
   362 
   363     assert(__ stackDepth() == 0);
   364 }
   365 
   366 void
   367 SemanticAnalysis::visitWhileStatement(WhileStatement *node)
   368 {
   369     PoolScope poolScope(zone_->pool());
   370     RootScope rootScope(zone_);
   371 
   372     Label header, join;
   373 
   374     __ bind(&header);
   375 
   376     ControlStatus status;
   377 
   378     LoopScope loop(scope_, &join, &header, &loop_);
   379     if (node->token() == TOK_WHILE) {
   380         Label body;
   381         visitForTest(node->condition(), &body, &join, &body);
   382         status = visitLoopBody(node->body());
   383         __ jump(&header);
   384     } else {
   385         status = visitLoopBody(node->body());
   386         visitForTest(node->condition(), &header, &join, &join);
   387     }
   388 
   389     __ bind(&join);
   390 
   391     // Detect loops that will always have a fork in the contro-flow graph.
   392     // This will be a |while| loop, or a |do-while| loop whose body does
   393     // not terminate. For now, we treat these as an |if| regardless of the
   394     // direction the branch can take. That means the control-flow is always
   395     // conditional.
   396     if (node->token() == TOK_WHILE || status.terminates() || loop.breaks()) {
   397         control_->merge(status, ControlStatus(false, Returns_Never));
   398     } else {
   399         // At this point, we've got a do-while loop with a |return| or
   400         // |continue|, meaning that the rest of the block is unreachable.
   401         control_->terminate(status.returns());
   402     }
   403 
   404     assert(__ stackDepth() == 0);
   405 }
   406 
   407 static inline Heap::Tenure
   408 InferTenure(Symbol *sym)
   409 {
   410     if (sym->scope()->kind() == Scope::GLOBAL)
   411         return Heap::Tenure_Old;
   412 
   413     // SP2's array semantics allow any array kind to escape, so we must use
   414     // the normal heap. (Hopefully escape analysis can ease this pain later).
   415     if (sym->type()->isArray())
   416         return Heap::Tenure_Default;
   417 
   418     return Heap::Tenure_Default;
   419 }
   420 
   421 void
   422 SemanticAnalysis::visitVariableDeclaration(VariableDeclaration *node)
   423 {
   424     PoolScope poolScope(zone_->pool());
   425     RootScope rootScope(zone_);
   426 
   427     if (node->initialization()) {
   428         HIR *hir = NULL;
   429 
   430         if ((hir = eval(node->initialization())) == NULL)
   431             return;
   432         if ((hir = coerce(hir, node->sym()->type(), Coerce_Assign)) == NULL)
   433             return;
   434 
   435         discharge(hir);
   436     } else {
   437         if (node->sym()->type()->isInt32() ||
   438             node->sym()->type()->isEnum() ||
   439             node->sym()->type()->isChar() ||
   440             node->sym()->type()->isBool())
   441         {
   442             __ int_(0);
   443         } else if (node->sym()->type()->isFloat()) {
   444             __ float_(0);
   445         } else if (node->sym()->type()->isArray()) {
   446             Local<ArrayType> type(zone_, ArrayType::cast(node->sym()->type()));
   447             Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
   448             if (!map)
   449                 return;
   450 
   451             if (type->isFixedLength()) {
   452                 __ newarray(OP_NEWFIXED, map, InferTenure(node->sym()));
   453             } else if (node->dims()) {
   454                 assert(false);
   455                 __ newarray(OP_NEWSIZED, map, InferTenure(node->sym()));
   456             } else {
   457                 __ newarray(OP_NEWEMPTY, map, InferTenure(node->sym()));
   458             }
   459         }
   460     }
   461 
   462     if (!__ allocate(node->sym()))
   463         return;
   464 
   465     set(node->sym());
   466     __ pop();
   467 }
   468 
   469 void
   470 SemanticAnalysis::visitReturnStatement(ReturnStatement *node)
   471 {
   472     control_->returns(Returns_Always);
   473 
   474     if (!node->expression()) {
   475         if (!fun_->returnType()->isVoid()) {
   476             cc_.reportError(node->pos(), Message_MissingReturnValue);
   477             return;
   478         }
   479 
   480         __ returnvoid();
   481         return;
   482     }
   483 
   484     if (fun_->returnType()->isVoid()) {
   485         cc_.reportError(node->pos(), Message_UsedVoidReturn);
   486         return;
   487     }
   488 
   489     PoolScope poolScope(zone_->pool());
   490     RootScope rootScope(zone_);
   491 
   492     HIR *hir = eval(node->expression());
   493     if (!hir)
   494         return;
   495 
   496     Local<Type> returnType(zone_, fun_->returnType());
   497     if ((hir = coerce(hir, returnType, Coerce_Return)) == NULL)
   498         return;
   499 
   500     discharge(hir);
   501 
   502     if (hir->type()->isVoid())
   503         __ returnvoid();
   504     else
   505         __ return_();
   506 }
   507 
   508 void
   509 SemanticAnalysis::visitBinaryExpression(BinaryExpression *node)
   510 {
   511     HIR *left = eval(node->left());
   512     HIR *right = eval(node->right());
   513     if (!left || !right)
   514         return;
   515 
   516     hir_ = binary(node, node->token(), left, right);
   517 }
   518 
   519 bool
   520 SemanticAnalysis::checkArgumentCount(Handle<FunctionType> type, unsigned actual)
   521 {
   522     if (type->parameters()->length() == actual)
   523         return true;
   524 
   525     if (actual > type->parameters()->length()) {
   526         if (!type->isNative() || !type->isNativeVariadic())
   527             return false;
   528         return true;
   529     }
   530 
   531     if (!type->defaults())
   532         return false;
   533 
   534     // Missing arguments. See if there's a default argument for each missing
   535     // actual.
   536     for (unsigned i = actual; i < type->parameters()->length(); i++) {
   537         if (!type->defaults()->at(i))
   538             return false;
   539     }
   540 
   541     return true;
   542 }
   543 
   544 void
   545 SemanticAnalysis::visitNameProxy(NameProxy *proxy)
   546 {
   547     Symbol *sym = proxy->sym();
   548     VariableSymbol *var = sym->asVariable();
   549 
   550     Scope *in = sym->scope();
   551     switch (in->kind()) {
   552       case Scope::GLOBAL:
   553         hir_ = new (pool_) HGlobal(proxy, sym);
   554         return;
   555 
   556       case Scope::FUNCTION:
   557         assert(var->storage() == VariableSymbol::Arg);
   558         hir_ = new (pool_) HLocal(proxy, var);
   559         return;
   560 
   561       default:
   562         assert(in->kind() == Scope::BLOCK);
   563         assert(var->storage() == VariableSymbol::Local);
   564         hir_ = new (pool_) HLocal(proxy, var);
   565         return;
   566     }
   567 }
   568 
   569 void
   570 SemanticAnalysis::visitIntegerLiteral(IntegerLiteral *lit)
   571 {
   572     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   573     hir_ = new (pool_) HInteger(lit, type, lit->value());
   574 }
   575 
   576 void
   577 SemanticAnalysis::visitFloatLiteral(FloatLiteral *node)
   578 {
   579     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
   580     hir_ = new (pool_) HFloat(node, type, (float)node->value());
   581 }
   582 
   583 void
   584 SemanticAnalysis::visitCallExpression(CallExpression *node)
   585 {
   586     HIR *callee = eval(node->callee());
   587     if (!callee)
   588         return;
   589 
   590     if (!callee->type()->isFunction()) {
   591         cc_.reportError(node->pos(), Message_CalleeNotFunction);
   592         return;
   593     }
   594 
   595     Local<FunctionType> fun(zone_, FunctionType::cast(callee->type()));
   596     
   597     if (!checkArgumentCount(fun, node->arguments()->length())) {
   598         cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
   599         return;
   600     }
   601 
   602     if (fun->isForward()) {
   603         cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
   604         return;
   605     }
   606 
   607     HIRList *args = new (pool_) HIRList;
   608     for (unsigned i = 0; i < node->arguments()->length(); i++) {
   609         Expression *expression = node->arguments()->at(i);
   610         HIR *arg = eval(expression);
   611         if (!arg)
   612             return;
   613 
   614         Handle<Type> given = arg->type();
   615         
   616         bool mustComputeReference;
   617         if (i >= fun->parameters()->length()) {
   618             // Special handling for natives. Arguments past the formal must
   619             // always have references computed. However, arrays are already
   620             // references for natives.
   621             assert(fun->isNative() && fun->isNativeVariadic());
   622             mustComputeReference = !given->isReference() &&
   623                                    !given->isArray();
   624         } else {
   625             Local<Type> actual(zone_, fun->parameterAt(i));
   626 
   627             if (expression->isIndexExpression()) {
   628                 // Temporarily disabled.
   629                 assert(!actual->isArray());
   630                 if (actual->isReference()) {
   631                     cc_.reportError(expression->pos(), Message_CannotComputeIndexRef);
   632                     return;
   633                 }
   634             }
   635 
   636             if (actual->isReference()) {
   637                 // If the actual is a reference, the coercion rules are much
   638                 // stricter; the contained types must be identical.
   639                 // :TODO: make this not an assert
   640                 assert(ReferenceType::cast(actual)->contained() == arg->type());
   641             } else {
   642                 // When we start overloading, coercion will have to happen later.
   643                 arg = coerce(arg, actual, Coerce_Arg);
   644                 if (!arg)
   645                     return;
   646             }
   647 
   648             mustComputeReference = actual->isReference() && !given->isReference();
   649         }
   650 
   651         if (mustComputeReference) {
   652             // Refs always use the LIFO stack if they can.
   653             arg = new (pool_) HToRef(arg->node(), arg->type(), arg);
   654             requireLifoStack();
   655         }
   656 
   657         if (!args->append(arg))
   658             return;
   659     }
   660 
   661     hir_ = new (pool_) HCall(node, fun->returnType(), callee, args);
   662 }
   663 
   664 void
   665 SemanticAnalysis::visitAssignment(Assignment *node)
   666 {
   667     HLValue *lval = lvalue(node->lvalue());
   668     if (!lval)
   669         return;
   670 
   671     HIR *hir = eval(node->expression());
   672     if ((hir = coerce(hir, lval->type(), Coerce_Assign)) == NULL)
   673         return;
   674 
   675     hir_ = new (pool_) HStore(node, node->token(), lval, hir);
   676 }
   677 
   678 void
   679 SemanticAnalysis::visitBreakStatement(BreakStatement *node)
   680 {
   681     if (!loop_) {
   682         cc_.reportError(node->pos(), Message_BreakOutsideLoop);
   683         return;
   684     }
   685 
   686     loop_->setBreaks();
   687     __ j(OP_BREAK, loop_->break_());
   688 }
   689 
   690 void
   691 SemanticAnalysis::visitContinueStatement(ContinueStatement *node)
   692 {
   693     if (!loop_) {
   694         cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
   695         return;
   696     }
   697 
   698     __ j(OP_CONTINUE, loop_->continue_());
   699 }
   700 
   701 void
   702 SemanticAnalysis::visitIndexExpression(IndexExpression *node)
   703 {
   704     HIR *left = eval(node->left());
   705     if (!left)
   706         return;
   707 
   708     HIR *right = eval(node->right());
   709     if (!right)
   710         return;
   711 
   712     // Hrm... yes, for now, let's coerce here.
   713     Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   714     if ((right = coerce(right, i32, Coerce_Arg)) == NULL)
   715         return;
   716     
   717     // Do not coerce here, there's no reason to yet.
   718     if (!left->type()->isArray()) {
   719         cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
   720         return;
   721     }
   722 
   723     hir_ = new (pool_) HIndex(node,
   724                               ArrayType::cast(left->type())->contained(),
   725                               left,
   726                               right);
   727 }
   728 
   729 void
   730 SemanticAnalysis::visitIncDecExpression(IncDecExpression *node)
   731 {
   732     HLValue *lval = lvalue(node->expression());
   733     if (!lval)
   734         return;
   735 
   736     if (!lval->type()->isInt32() && !lval->type()->isFloat()) {
   737         assert(false);
   738         return;
   739     }
   740 
   741     HIR *rval;
   742     if (lval->type()->isInt32())
   743         rval = new (pool_) HInteger(node, lval->type(), 1);
   744     else
   745         rval = new (pool_) HFloat(node, lval->type(), 1.0);
   746 
   747     if (node->postfix())
   748         hir_ = new (pool_) HPostIncDec(node, node->token(), lval, rval);
   749     else
   750         hir_ = new (pool_) HStore(node, node->token(), lval, rval);
   751 }
   752 
   753 Type *
   754 SemanticAnalysis::coercionType(TokenKind token, HIR *left, HIR *right)
   755 {
   756     Handle<Type> l = left->type();
   757     Handle<Type> r = right->type();
   758 
   759     if (token >= TOK_PLUS && token <= TOK_SLASH) {
   760         // We allow: [float|int32] + [float|int32]
   761         if (l->isFloat() && r->isInt32())
   762             return l;
   763         if (l->isInt32() && r->isFloat())
   764             return r;
   765         if (l->isInt32() && r->isInt32())
   766             return l;
   767     }
   768 
   769     // :TODO: remove
   770     assert(l == r);
   771 
   772     return left->type();
   773 }
   774 
   775 bool
   776 SemanticAnalysis::typeCheckArray(const SourcePosition &pos,
   777                                  Handle<Type> argGiven,
   778                                  Handle<Type> argActual,
   779                                  CoercionKind kind)
   780 {
   781     if (!argGiven->isArray()) {
   782         cc_.reportError(pos, Message_ExpectedArray);
   783         return false;
   784     }
   785 
   786     Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
   787     Local<ArrayType> given(zone_, ArrayType::cast(argGiven));
   788 
   789     if (actual->levels() != given->levels()) {
   790         cc_.reportError(pos, Message_ArrayDimensionsMismatch);
   791         return false;
   792     }
   793 
   794     unsigned level = 1;
   795     while (true) {
   796         if (actual->isFixedLength()) {
   797             if (kind == Coerce_Return || kind == Coerce_Assign) {
   798                 if (!given->isFixedLength()) {
   799                     cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
   800                     return false;
   801                 }
   802 
   803                 if (actual->isCharArray()) {
   804                     // String assignment can have a truncated |given|.
   805                     if (given->fixedLength() > actual->fixedLength()) {
   806                         cc_.reportError(pos, Message_ArrayAssignmentTooBig);
   807                         return false;
   808                     }
   809                 } else {
   810                     if (given->fixedLength() != actual->fixedLength()) {
   811                         cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
   812                         return false;
   813                     }
   814                 }
   815             }
   816         } else if (given->isFixedLength()) {
   817             // We do not allow assignments in the form:
   818             //  [][] = [][Y]
   819             //
   820             // Otherwise, the following code could break the size guarantees
   821             // of the right-hand side:
   822             //
   823             //  new x[][5];
   824             //  new y[][];
   825             //  new z[3];
   826             //
   827             //
   828             //  y = x;
   829             //  y[0] = z;
   830             //
   831             // Now |x[0]| contains a 3-length array.
   832             if (level > 1) {
   833                 cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
   834                 return false;
   835             }
   836         }
   837 
   838         if (!given->contained()->isArray() || !actual->contained()->isArray())
   839             break;
   840 
   841         given = ArrayType::cast(given->contained());
   842         actual = ArrayType::cast(actual->contained());
   843     }
   844 
   845     // These arrays must contain the same innermost type.
   846     if (given->contained() != actual->contained()) {
   847         cc_.reportError(pos, Message_TypeMismatch,
   848                         GetTypeName(actual->contained()),
   849                         GetTypeName(given->contained()));
   850         return false;
   851     }
   852 
   853     return true;
   854 }
   855 
   856 HIR *
   857 SemanticAnalysis::coerce(HIR *hir, Handle<Type> to, CoercionKind kind)
   858 {
   859     Handle<Type> from = hir->type();
   860 
   861     if (from->isInt32() && to->isFloat())
   862         return new (pool_) HConvert(hir->node(), to, OP_CVT_I2F, hir);
   863     if (from->isInt32() && to->isBool())
   864         return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir);
   865     
   866     if (to->isArray()) {
   867         if (!typeCheckArray(SourcePosition(), from, to, kind))
   868             return NULL;
   869         return hir;
   870     }
   871     
   872     return hir;
   873 }
   874 
   875 void
   876 SemanticAnalysis::set(VariableSymbol *sym)
   877 {
   878     if (sym->scope()->kind() == Scope::GLOBAL) {
   879         __ setglobal(sym);
   880     } else {
   881         assert(sym->storage() == VariableSymbol::Local);
   882         __ setlocal(sym);
   883     }
   884 }
   885 
   886 HIR *
   887 SemanticAnalysis::binary(AstNode *node, TokenKind token, HIR *left, HIR *right)
   888 {
   889     Local<Type> coercion(zone_, coercionType(token, left, right));
   890     if (!coercion)
   891         return NULL;
   892     if ((left = coerce(left, coercion, Coerce_Arg)) == NULL)
   893         return NULL;
   894     if ((right = coerce(right, coercion, Coerce_Arg)) == NULL)
   895         return NULL;
   896     
   897     switch (token) {
   898      case TOK_PLUS:
   899       case TOK_MINUS:
   900       case TOK_STAR:
   901       case TOK_SLASH:
   902       case TOK_PERCENT:
   903       case TOK_AMPERSAND:
   904       case TOK_BITOR:
   905       case TOK_BITXOR:
   906       case TOK_SHR:
   907       case TOK_USHR:
   908       case TOK_SHL:
   909         return new (pool_) HBinary(node, left->type(), token, left, right);
   910 
   911       case TOK_EQUALS:
   912       case TOK_NOTEQUALS:
   913       case TOK_LT:
   914       case TOK_LE:
   915       case TOK_GT:
   916       case TOK_GE:
   917       case TOK_AND:
   918       case TOK_OR:
   919       {
   920         Local<Type> result(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
   921         return new (pool_) HBinary(node, result, token, left, right);
   922       }
   923 
   924       default:
   925         assert(false);
   926         return NULL;
   927     }
   928 }
   929 
   930 static inline TokenKind
   931 ToCompare(Expression *expr)
   932 {
   933     if (expr->isBinaryExpression()) {
   934         BinaryExpression *b = expr->toBinaryExpression();
   935         if (b->token() >= TOK_EQUALS && b->token() <= TOK_OR)
   936             return b->token();
   937     } else if (expr->isUnaryExpression()) {
   938         UnaryExpression *u = expr->toUnaryExpression();
   939         if (u->token() == TOK_NOT)
   940             return TOK_NOT;
   941     }
   942     return TOK_EOF;
   943 }
   944 
   945 void
   946 SemanticAnalysis::visitForTest(Expression *expr,
   947                                Label *trueBranch,
   948                                Label *falseBranch,
   949                                Label *fallthrough)
   950 {
   951     Local<Type> boolType(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
   952 
   953     TokenKind token = ToCompare(expr);
   954     if (token == TOK_EOF || token == TOK_NOT) {
   955         HIR *hir;
   956         if (token == TOK_EOF)
   957             hir = eval(expr);
   958         else
   959             hir = eval(expr->toUnaryExpression()->expression());
   960         if (!hir)
   961             return;
   962         if ((hir = coerce(hir, boolType, Coerce_Assign)) == NULL)
   963             return;
   964 
   965         discharge(hir);
   966 
   967         bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
   968         Opcode op = jumpOnTrue ? OP_JT : OP_JF;
   969         
   970         if (fallthrough == falseBranch)
   971             __ j(op, trueBranch);
   972         else
   973             __ j(op, falseBranch);
   974         return;
   975     }
   976 
   977     BinaryExpression *bin = expr->toBinaryExpression();
   978     if (token == TOK_AND || token == TOK_OR) {
   979         assert(false);
   980         //visitForLogicTest(expr, trueBranch, falseBranch, fallthrough);
   981         return;
   982     }
   983 
   984     HIR *left = eval(bin->left());
   985     HIR *right = eval(bin->right());
   986     if (!left || !right)
   987         return;
   988 
   989     HIR *hir = binary(bin, bin->token(), left, right);
   990     if (!hir)
   991         return;
   992     if ((hir = coerce(hir, boolType, Coerce_Assign)) == NULL)
   993         return;
   994 
   995     discharge(hir);
   996     if (fallthrough == trueBranch)
   997         __ j(OP_JF, falseBranch);
   998     else
   999         __ j(OP_JT, trueBranch);
  1000 }
  1001 
  1002 HLValue *
  1003 SemanticAnalysis::lvalue(Expression *expr)
  1004 {
  1005     HIR *hir = eval(expr);
  1006     if (!hir)
  1007         return NULL;
  1008     
  1009     if (!hir->isLValue()) {
  1010         cc_.reportError(expr->pos(), Message_ExpectedLValue);
  1011         return NULL;
  1012     }
  1013 
  1014     return static_cast<HLValue *>(hir);
  1015 }
  1016 
  1017 HIR *
  1018 SemanticAnalysis::eval(Expression *expr)
  1019 {
  1020     assert(!hir_);
  1021     expr->accept(this);
  1022 
  1023     HIR *hir = hir_;
  1024     hir_ = NULL;
  1025 
  1026     return hir;
  1027 }
  1028 
  1029 void
  1030 SemanticAnalysis::discharge(HIR *hir)
  1031 {
  1032     EmitHIR(zone_, emitter_, hir);
  1033 }