src/compiler/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jan 01 20:08:34 2013 -0800 (2013-01-01)
changeset 255 b3cf7e052ddf
parent 251 ca99a81745fe
child 256 3c184218462d
permissions -rw-r--r--
Fix FileSystem.cpp build on GCC.
     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     loop_(NULL)
    68 {
    69 }
    70 
    71 SemanticAnalysis::SemanticAnalysis(SemanticAnalysis *parent, Handle<FunctionType> fun)
    72   : zone_(parent->zone_),
    73     pool_(parent->pool_),
    74     cc_(parent->cc_),
    75     unit_(parent->unit_),
    76     hir_(NULL),
    77     scope_(parent->scope_),
    78     emitter_(pool_),
    79     fun_(fun),
    80     loop_(NULL),
    81     control_(NULL)
    82 {
    83 
    84 }
    85 
    86 void
    87 SemanticAnalysis::analyze()
    88 {
    89     scope_ = unit_->globalScope();
    90 
    91     for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
    92         Statement *stmt = unit_->tree()->statements()->at(i);
    93         stmt->accept(this);
    94     }
    95 
    96     Local<Struct> globals(zone_, unit_->globalScope()->build(zone_));
    97     if (!globals)
    98         return;
    99     unit_->module()->setGlobals(globals);
   100 
   101     Local<Code> code(zone_, __ finish());
   102     if (!code)
   103         return;
   104     code->setModule(unit_->module());
   105     unit_->module()->setCode(code);
   106 
   107 #ifndef NDEBUG
   108 //    Disassemble(code, stdout);
   109 #endif
   110 }
   111 
   112 void
   113 SemanticAnalysis::visitFunctionStatement(FunctionStatement *stmt)
   114 {
   115     FunctionSymbol *sym = stmt->sym();
   116     Local<FunctionType> type(zone_, sym->type());
   117 
   118     assert(scope_->kind() == Scope::GLOBAL);
   119 
   120     if (stmt->token() == TOK_NATIVE) {
   121         // Define the native now.
   122         size_t index;
   123         if (!zone_->nativeTable()->add(stmt->name(), &index))
   124             return;
   125 
   126         Local<Native> native(zone_, Native::New(zone_, type, index));
   127         if (!native)
   128             return;
   129 
   130         __ object(native);
   131         __ setglobal(sym);
   132         __ pop();
   133     }
   134 
   135     // If the function is a forward or native, we don't have to do anything.
   136     if (stmt->token() == TOK_NATIVE || stmt->token() == TOK_FORWARD)
   137         return;
   138 
   139     SemanticAnalysis child(this, type);
   140     Local<Function> funobj(zone_, child.compile(stmt));
   141     if (!funobj)
   142         return;
   143 
   144     __ object(funobj);
   145     __ setglobal(sym);
   146     if (stmt->token() == TOK_PUBLIC)
   147         __ public_();
   148     else
   149         __ pop();
   150 }
   151 
   152 Function *
   153 SemanticAnalysis::compile(FunctionStatement *stmt)
   154 {
   155     __ setFirstLine(stmt->pos().line);
   156 
   157     AutoEnterScope argScope(&scope_, stmt->argScope());
   158 
   159     for (size_t i = 0; i < stmt->signature().parameters()->length(); i++) {
   160         Parameter *param = stmt->signature().parameters()->at(i);
   161         param->sym()->allocate(VariableSymbol::Arg, i);
   162     }
   163 
   164     AutoEnterScope varScope(&scope_, stmt->varScope());
   165     ControlStatus status = visitForControl(stmt->body());
   166 
   167     if (!fun_->returnType()->isVoid()) {
   168         // If the function is not void, report if not all paths return a value.
   169         // All other incorrect return cases have been caught already.
   170         if (status.returns() == Returns_Sometimes) {
   171             cc_.reportError(stmt->pos(), Message_NotAllPathsReturnValue);
   172             return NULL;
   173         }
   174 
   175         if (status.returns() == Returns_Never) {
   176             cc_.reportError(stmt->pos(), Message_MissingReturnValue);
   177             return NULL;
   178         }
   179     }
   180 
   181     Local<Code> code(zone_, __ finish());
   182     if (!code)
   183         return NULL;
   184     code->setModule(unit_->module());
   185 
   186     Local<Function> fun(zone_, Function::New(zone_, code, fun_, stmt->name(), stmt->pos()));
   187     if (!fun)
   188         return NULL;
   189 
   190 #ifndef NDEBUG
   191 //    Disassemble(code, stdout);
   192 #endif
   193 
   194     return fun;
   195 }
   196 
   197 void 
   198 SemanticAnalysis::visitBlockStatement(BlockStatement *node)
   199 {
   200     AutoEnterScope scope(&scope_, node->scope());
   201 
   202     for (size_t i = 0; i < node->statements()->length(); i++) {
   203         Statement *stmt = node->statements()->at(i);
   204         __ note_position(stmt->pos());
   205         stmt->accept(this);
   206         assert(__ stackDepth() == 0);
   207     }
   208 }
   209 
   210 void
   211 SemanticAnalysis::visitEnumStatement(EnumStatement *node)
   212 {
   213 }
   214 
   215 void
   216 SemanticAnalysis::visitExpressionStatement(ExpressionStatement *node)
   217 {
   218     // While building HIR, we enter new pool and root scopes, since HIR
   219     // creation is purely temporary.
   220     PoolScope poolScope(zone_->pool());
   221     RootScope rootScope(zone_);
   222 
   223     HIR *hir = eval(node->expression());
   224     if (!hir)
   225         return;
   226 
   227     discharge(hir);
   228     if (!hir->type()->isVoid())
   229         __ pop();
   230 }
   231 
   232 void
   233 SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
   234 {
   235     // If both sides terminate in a return, we consider this a return as well.
   236     if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
   237         terminate(Returns_Always);
   238         return;
   239     }
   240 
   241     ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
   242                           ? Returns_Never
   243                           : Returns_Sometimes;
   244 
   245     if (left.terminates() && right.terminates())
   246         terminate(status);
   247     else
   248         returns(status);
   249 }
   250 
   251 SemanticAnalysis::ControlStatus
   252 SemanticAnalysis::visitForControl(Statement *statement)
   253 {
   254     ControlScope scope(&control_);
   255     statement->accept(this);
   256     return scope.status();
   257 }
   258 
   259 void
   260 SemanticAnalysis::visitIfStatement(IfStatement *node)
   261 {
   262     Label join;
   263 
   264     ControlStatus trueBranch;
   265     ControlStatus falseBranch(false, Returns_Never);
   266 
   267     if (!node->ifFalse()) {
   268         Label success;
   269 
   270         visitForTest(node->condition(), &success, &join, &success);
   271         __ bind(&success);
   272         trueBranch = visitForControl(node->ifTrue());
   273     } else {
   274         Label success, next;
   275 
   276         visitForTest(node->condition(), &success, &next, &success);
   277         __ bind(&success);
   278         trueBranch = visitForControl(node->ifTrue());
   279         __ jump(&join);
   280         __ bind(&next);
   281         falseBranch = visitForControl(node->ifFalse());
   282     }
   283 
   284     __ bind(&join);
   285 
   286     control_->merge(trueBranch, falseBranch);
   287 }
   288 
   289 void
   290 SemanticAnalysis::requireLifoStack()
   291 {
   292     if (!loop_)
   293         return;
   294 
   295     loop_->setUsesLifoStack();
   296 }
   297 
   298 SemanticAnalysis::ControlStatus
   299 SemanticAnalysis::visitLoopBody(Statement *stmt)
   300 {
   301     // We always mark off a loop body, so on each edge, we can balance the
   302     // LIFO stack. Right now, we don't have the ability to budget the LIFO
   303     // stack ahead of time. If we turn out to never need the LIFO stack, we
   304     // mark it as unnecessary. (The interpreter can't really make use of this,
   305     // but the JIT can).
   306     //
   307     // Note that balancing the LIFO stack isn't even necessary, so this
   308     // feature may be removed. All this mechanism does is mitigate the
   309     // possibility that a long-running loop will overflow the LIFO region
   310     // and therefore start requiring nursery allocations.
   311     int pos = __ enterloop();
   312     ControlStatus status = visitForControl(stmt);
   313     __ leaveloop();
   314 
   315     if (loop_->usesLifoStack())
   316         __ setLoopUsesLifoStack(pos);
   317 
   318     return status;
   319 }
   320 
   321 void
   322 SemanticAnalysis::visitForStatement(ForStatement *node)
   323 {
   324     AutoEnterScope scope(&scope_, node->scope());
   325     PoolScope poolScope(zone_->pool());
   326     RootScope rootScope(zone_);
   327 
   328     Label join, update;
   329     LoopScope loop(scope_, &join, &update, &loop_);
   330 
   331     if (node->initialization())
   332         node->initialization()->accept(this);
   333 
   334     Label header, test;
   335     if (node->condition())
   336         __ jump(&test);
   337 
   338     __ bind(&header);
   339     ControlStatus status = visitLoopBody(node->body());
   340 
   341     __ bind(&update);
   342     if (node->update())
   343         node->update()->accept(this);
   344 
   345     if (node->condition()) {
   346         __ bind(&test);
   347         visitForTest(node->condition(), &header, &join, &join);
   348     } else {
   349         __ jump(&header);
   350     }
   351 
   352     __ bind(&join);
   353     
   354     // If there was a condition, we treat this like a while loop. Otherwise,
   355     // the join point is only reachable if the loop contains a break. The
   356     // termination status doesn't tell us anything yet.
   357     if (node->condition() || loop.breaks())
   358         control_->merge(status, ControlStatus(false, Returns_Never));
   359     else
   360         control_->terminate(status.returns());
   361 
   362     assert(__ stackDepth() == 0);
   363 }
   364 
   365 void
   366 SemanticAnalysis::visitWhileStatement(WhileStatement *node)
   367 {
   368     PoolScope poolScope(zone_->pool());
   369     RootScope rootScope(zone_);
   370 
   371     Label header, join;
   372 
   373     __ bind(&header);
   374 
   375     ControlStatus status;
   376 
   377     LoopScope loop(scope_, &join, &header, &loop_);
   378     if (node->token() == TOK_WHILE) {
   379         Label body;
   380         visitForTest(node->condition(), &body, &join, &body);
   381         status = visitLoopBody(node->body());
   382         __ jump(&header);
   383     } else {
   384         status = visitLoopBody(node->body());
   385         visitForTest(node->condition(), &header, &join, &join);
   386     }
   387 
   388     __ bind(&join);
   389 
   390     // Detect loops that will always have a fork in the contro-flow graph.
   391     // This will be a |while| loop, or a |do-while| loop whose body does
   392     // not terminate. For now, we treat these as an |if| regardless of the
   393     // direction the branch can take. That means the control-flow is always
   394     // conditional.
   395     if (node->token() == TOK_WHILE || status.terminates() || loop.breaks()) {
   396         control_->merge(status, ControlStatus(false, Returns_Never));
   397     } else {
   398         // At this point, we've got a do-while loop with a |return| or
   399         // |continue|, meaning that the rest of the block is unreachable.
   400         control_->terminate(status.returns());
   401     }
   402 
   403     assert(__ stackDepth() == 0);
   404 }
   405 
   406 static inline Heap::Tenure
   407 InferTenure(Symbol *sym)
   408 {
   409     if (sym->scope()->kind() == Scope::GLOBAL)
   410         return Heap::Tenure_Old;
   411 
   412     // SP2's array semantics allow any array kind to escape, so we must use
   413     // the normal heap. (Hopefully escape analysis can ease this pain later).
   414     if (sym->type()->isArray())
   415         return Heap::Tenure_Default;
   416 
   417     return Heap::Tenure_Default;
   418 }
   419 
   420 void
   421 SemanticAnalysis::visitVariableDeclaration(VariableDeclaration *node)
   422 {
   423     PoolScope poolScope(zone_->pool());
   424     RootScope rootScope(zone_);
   425 
   426     Local<Type> type(zone_, node->sym()->type());
   427 
   428     if (node->sym()->type()->isVoid()) {
   429         cc_.reportError(node->type()->pos(), Message_CannotDeclareVoid);
   430         return;
   431     }
   432 
   433     if (node->initialization()) {
   434         HIR *hir = NULL;
   435 
   436         if ((hir = eval(node->initialization())) == NULL)
   437             return;
   438         if ((hir = coerce(hir, type, Coerce_Decl)) == NULL)
   439             return;
   440 
   441         discharge(hir);
   442     } else {
   443         if (type->isInt32() || type->isEnum() ||
   444             type->isChar() || type->isBool())
   445         {
   446             __ int_(0);
   447         } else if (type->isFloat()) {
   448             __ float_(0);
   449         } else if (type->isArray()) {
   450             Local<ArrayType> atype(zone_, ArrayType::cast(type));
   451             Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, atype));
   452             if (!map)
   453                 return;
   454 
   455             if (atype->isFixedLength()) {
   456                 __ newarray(OP_NEWFIXED, map, InferTenure(node->sym()));
   457             } else if (node->dims()->at(0)) {
   458                 // This may not be true if we allow typedefing, so :TODO:
   459                 // figure out proper semantics.
   460                 assert(node->dims()->length() == atype->levels());
   461 
   462                 Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   463                 for (size_t i = 0; i < node->dims()->length(); i++) {
   464                     Expression *expr = node->dims()->at(i);
   465                     if (expr) {
   466                         HIR *hir = eval(expr);
   467                         if (!hir || ((hir = coerce(hir, i32, Coerce_Arg)) == NULL))
   468                             return;
   469                         discharge(hir);
   470                     } else {
   471                         __ int_(0);
   472                     }
   473                 }
   474                 __ newarray(OP_NEWSIZED, map, InferTenure(node->sym()));
   475             } else {
   476                 __ newarray(OP_NEWEMPTY, map, InferTenure(node->sym()));
   477             }
   478         } else {
   479             assert(false);
   480         }
   481     }
   482 
   483     if (node->sym()->scope()->kind() != Scope::GLOBAL) {
   484         if (!__ allocate(node->sym()))
   485             return;
   486     }
   487 
   488     set(node->sym());
   489     __ pop();
   490 }
   491 
   492 void
   493 SemanticAnalysis::visitReturnStatement(ReturnStatement *node)
   494 {
   495     control_->returns(Returns_Always);
   496 
   497     if (!node->expression()) {
   498         if (!fun_->returnType()->isVoid()) {
   499             cc_.reportError(node->pos(), Message_MissingReturnValue);
   500             return;
   501         }
   502 
   503         __ returnvoid();
   504         return;
   505     }
   506 
   507     if (fun_->returnType()->isVoid()) {
   508         cc_.reportError(node->pos(), Message_UsedVoidReturn);
   509         return;
   510     }
   511 
   512     PoolScope poolScope(zone_->pool());
   513     RootScope rootScope(zone_);
   514 
   515     HIR *hir = eval(node->expression());
   516     if (!hir)
   517         return;
   518 
   519     Local<Type> returnType(zone_, fun_->returnType());
   520     if ((hir = coerce(hir, returnType, Coerce_Return)) == NULL)
   521         return;
   522 
   523     discharge(hir);
   524 
   525     if (hir->type()->isVoid())
   526         __ returnvoid();
   527     else
   528         __ return_();
   529 }
   530 
   531 void
   532 SemanticAnalysis::visitBinaryExpression(BinaryExpression *node)
   533 {
   534     HIR *left = eval(node->left());
   535     HIR *right = eval(node->right());
   536     if (!left || !right)
   537         return;
   538 
   539     hir_ = binary(node, node->token(), left, right);
   540 }
   541 
   542 bool
   543 SemanticAnalysis::checkArgumentCount(Handle<FunctionType> type, unsigned actual)
   544 {
   545     if (type->parameters()->length() == actual)
   546         return true;
   547 
   548     if (actual > type->parameters()->length()) {
   549         if (!type->isNative() || !type->isNativeVariadic())
   550             return false;
   551         return true;
   552     }
   553 
   554     if (!type->defaults())
   555         return false;
   556 
   557     // Missing arguments. See if there's a default argument for each missing
   558     // actual.
   559     for (unsigned i = actual; i < type->parameters()->length(); i++) {
   560         if (!type->defaults()->at(i))
   561             return false;
   562     }
   563 
   564     return true;
   565 }
   566 
   567 void
   568 SemanticAnalysis::visitNameProxy(NameProxy *proxy)
   569 {
   570     Symbol *sym = proxy->sym();
   571 
   572     switch (sym->kind()) {
   573       case Symbol::kConstant:
   574       {
   575         ConstantSymbol *val = sym->toConstant();
   576         hir_ = new (pool_) HInteger(proxy, sym->type(), val->value().toInt());
   577         break;
   578       }
   579       
   580       // This is kind of screwy. Symbol::kFunction is like a constant we can't
   581       // evaluate yet. Maybe we should extract the GLOBAL case and say that
   582       // kFunction is only used for global functions (and use const vars for
   583       // local functions).
   584       case Symbol::kFunction:
   585       case Symbol::kVariable:
   586       {
   587         Scope *in = sym->scope();
   588         switch (in->kind()) {
   589           case Scope::GLOBAL:
   590             hir_ = new (pool_) HGlobal(proxy, sym);
   591             break;
   592 
   593           case Scope::FUNCTION:
   594           {
   595             VariableSymbol *var = sym->toVariable();
   596             assert(var->storage() == VariableSymbol::Arg);
   597             hir_ = new (pool_) HLocal(proxy, var);
   598             break;
   599           }
   600 
   601           default:
   602           {
   603             VariableSymbol *var = sym->toVariable();
   604             assert(in->kind() == Scope::BLOCK);
   605             assert(var->storage() == VariableSymbol::Local);
   606             hir_ = new (pool_) HLocal(proxy, var);
   607             break;
   608           }
   609         }
   610         break;
   611       }
   612 
   613       default:
   614         // :TODO:
   615         assert(false);
   616     }
   617 }
   618 
   619 void
   620 SemanticAnalysis::visitBooleanLiteral(BooleanLiteral *node)
   621 {
   622     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
   623     hir_ = new (pool_) HBoolean(node, type, node->token() == TOK_TRUE);
   624 }
   625 
   626 void
   627 SemanticAnalysis::visitIntegerLiteral(IntegerLiteral *lit)
   628 {
   629     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   630     hir_ = new (pool_) HInteger(lit, type, lit->value());
   631 }
   632 
   633 void
   634 SemanticAnalysis::visitFloatLiteral(FloatLiteral *node)
   635 {
   636     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
   637     hir_ = new (pool_) HFloat(node, type, (float)node->value());
   638 }
   639 
   640 void
   641 SemanticAnalysis::visitStringLiteral(StringLiteral *node)
   642 {
   643     Type *type = zone_->types()->getString();
   644     hir_ = new (pool_) HString(node, type, node->string());
   645 }
   646 
   647 void
   648 SemanticAnalysis::visitCallExpression(CallExpression *node)
   649 {
   650     HIR *callee = eval(node->callee());
   651     if (!callee)
   652         return;
   653 
   654     if (!callee->type()->isFunction()) {
   655         cc_.reportError(node->pos(), Message_CalleeNotFunction);
   656         return;
   657     }
   658 
   659     Local<FunctionType> fun(zone_, FunctionType::cast(callee->type()));
   660     
   661     if (!checkArgumentCount(fun, node->arguments()->length())) {
   662         cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
   663         return;
   664     }
   665 
   666     if (fun->isForward()) {
   667         cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
   668         return;
   669     }
   670 
   671     HIRList *args = new (pool_) HIRList;
   672     for (unsigned i = 0; i < node->arguments()->length(); i++) {
   673         Expression *expression = node->arguments()->at(i);
   674         HIR *arg = eval(expression);
   675         if (!arg)
   676             return;
   677 
   678         Handle<Type> given = arg->type();
   679         
   680         bool mustComputeReference;
   681         if (i >= fun->parameters()->length()) {
   682             // Special handling for natives. Arguments past the formal must
   683             // always have references computed. However, arrays are already
   684             // references for natives.
   685             assert(fun->isNative() && fun->isNativeVariadic());
   686             mustComputeReference = !given->isReference() &&
   687                                    !given->isArray();
   688         } else {
   689             Local<Type> actual(zone_, fun->parameterAt(i));
   690 
   691 
   692             if (expression->isIndexExpression() && arg->isIndex()) {
   693                 // If the expression is the form x[y], and this produced a
   694                 // normal array indexing operation, then we apply some 
   695                 // special rules.
   696 
   697                 if (actual->isReference()) {
   698                     // Disabled, since this doesn't have easily definable or
   699                     // sensible semantics with SP2 arrays, but we don't want
   700                     // to silently break SP1 semantics.
   701                     cc_.reportError(expression->pos(), Message_CannotComputeIndexRef);
   702                     return;
   703                 }
   704 
   705                 // As a special rule to account for SP1 semantics, we allow x[y]
   706                 // to automatically compute a sliced, read-only array view if
   707                 // the desired type is an array of one more dimension than x[y]
   708                 // would return.
   709                 //
   710                 // As an additional restriction, this is only allowed for
   711                 // one-level char arrays, to minimize potential issues until
   712                 // we determine whether more compatibility is needed.
   713                 //
   714                 // Internally, for sanity, the dependent array operation does
   715                 // not necessarily create a dependent array. For extensible
   716                 // arrays, we instead create a duplicate arrary of just the
   717                 // sliced portion, rather than deal with the complexity of the
   718                 // source array being resized.
   719                 //
   720                 // Note that we don't really know whether a dependent array
   721                 // will be dependent at compile-time, so the dependent type's
   722                 // just inherits from the source.
   723                 if (actual->isArray()) {
   724                     HIndex *index = arg->toIndex();
   725                     Local<ArrayType> basetype(zone_, ArrayType::cast(index->base()->type()));
   726                     Local<ArrayType> atype(zone_, ArrayType::cast(actual));
   727 
   728                     if (atype->isCharArray() && basetype->isCharArray()) {
   729                         // There is no possible way this will type check, so
   730                         // it's safe to just try something completely
   731                         // different.
   732                         Local<Type> slicetype(zone_);
   733                         if (basetype->isFixedLength()) {
   734                             // If the base type is fixed length, we need to
   735                             // compute a new dynamic array type based on the
   736                             // fixed array's contents and qualifiers.
   737                             Local<Type> contained(zone_, basetype->contained());
   738                             slicetype = zone_->types()->newArray(contained, ArrayType::DYNAMIC_ARRAY_SIZE);
   739                             if (!slicetype)
   740                                 return;
   741                             slicetype = zone_->types()->qualify(slicetype, basetype->quals());
   742                             if (!slicetype)
   743                                 return;
   744                         } else {
   745                             slicetype = basetype;
   746                         }
   747                         arg = new (pool_) HNewDependentArray(expression, slicetype, index->base(), index->index());
   748                         given = arg->type();
   749                     }
   750                 }
   751             }
   752 
   753             if (actual->isReference()) {
   754                 // If the actual is a reference, the coercion rules are much
   755                 // stricter; the contained types must be identical.
   756                 // :TODO: make this not an assert
   757                 assert(ReferenceType::cast(actual)->contained() == arg->type());
   758             } else {
   759                 // When we start overloading, coercion will have to happen later.
   760                 arg = coerce(arg, actual, Coerce_Arg);
   761                 if (!arg)
   762                     return;
   763             }
   764 
   765             mustComputeReference = actual->isReference() && !given->isReference();
   766         }
   767 
   768         if (mustComputeReference) {
   769             // Refs always use the LIFO stack if they can.
   770             arg = new (pool_) HToRef(arg->node(), arg->type(), arg);
   771             requireLifoStack();
   772         }
   773 
   774         if (!args->append(arg))
   775             return;
   776     }
   777 
   778     hir_ = new (pool_) HCall(node, fun->returnType(), callee, args);
   779 }
   780 
   781 void
   782 SemanticAnalysis::visitAssignment(Assignment *node)
   783 {
   784     HLValue *lval = lvalue(node->lvalue());
   785     if (!lval)
   786         return;
   787 
   788     if (lval->type()->quals() & TypeQual_Const) {
   789         cc_.reportError(node->pos(), Message_CannotModifyConst);
   790         return;
   791     }
   792 
   793     HIR *hir = eval(node->expression());
   794     if (!hir)
   795         return;
   796     if ((hir = coerce(hir, lval->type(), Coerce_Assign)) == NULL)
   797         return;
   798 
   799     hir_ = new (pool_) HStore(node, node->token(), lval, hir);
   800 }
   801 
   802 void
   803 SemanticAnalysis::visitBreakStatement(BreakStatement *node)
   804 {
   805     if (!loop_) {
   806         cc_.reportError(node->pos(), Message_BreakOutsideLoop);
   807         return;
   808     }
   809 
   810     loop_->setBreaks();
   811     __ j(OP_BREAK, loop_->break_());
   812 }
   813 
   814 void
   815 SemanticAnalysis::visitContinueStatement(ContinueStatement *node)
   816 {
   817     if (!loop_) {
   818         cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
   819         return;
   820     }
   821 
   822     __ j(OP_CONTINUE, loop_->continue_());
   823 }
   824 
   825 void
   826 SemanticAnalysis::visitIndexExpression(IndexExpression *node)
   827 {
   828     HIR *left = eval(node->left());
   829     if (!left)
   830         return;
   831 
   832     HIR *right = eval(node->right());
   833     if (!right)
   834         return;
   835 
   836     // Hrm... yes, for now, let's coerce here.
   837     Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   838     if ((right = coerce(right, i32, Coerce_Arg)) == NULL)
   839         return;
   840     
   841     // Do not coerce here, there's no reason to yet.
   842     if (!left->type()->isArray()) {
   843         cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
   844         return;
   845     }
   846 
   847     hir_ = new (pool_) HIndex(node,
   848                               ArrayType::cast(left->type())->contained(),
   849                               left,
   850                               right);
   851 }
   852 
   853 void
   854 SemanticAnalysis::visitIncDecExpression(IncDecExpression *node)
   855 {
   856     HLValue *lval = lvalue(node->expression());
   857     if (!lval)
   858         return;
   859 
   860     if (!lval->type()->isInt32() && !lval->type()->isFloat()) {
   861         assert(false);
   862         return;
   863     }
   864 
   865     HIR *rval;
   866     if (lval->type()->isInt32())
   867         rval = new (pool_) HInteger(node, lval->type(), 1);
   868     else
   869         rval = new (pool_) HFloat(node, lval->type(), 1.0);
   870 
   871     if (node->postfix())
   872         hir_ = new (pool_) HPostIncDec(node, node->token(), lval, rval);
   873     else
   874         hir_ = new (pool_) HStore(node, node->token(), lval, rval);
   875 }
   876 
   877 Type *
   878 SemanticAnalysis::coercionType(TokenKind token, HIR *left, HIR *right)
   879 {
   880     Local<Type> l(zone_, left->type());
   881     Local<Type> r(zone_, right->type());
   882 
   883     if (l->isPod())
   884         l = l->unqualified();
   885     if (r->isPod())
   886         r = r->unqualified();
   887 
   888     if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
   889         (token >= TOK_EQUALS && token <= TOK_GE))
   890     {
   891         // We allow: [float|int32] + [float|int32]
   892         if (l->isFloat() && r->isInt32())
   893             return l;
   894         if (l->isInt32() && r->isFloat())
   895             return r;
   896         if (l->isInt32() && r->isInt32())
   897             return l;
   898 
   899         if (l->isChar() && r->isInt32())
   900              return r;
   901         if (l->isInt32() && r->isChar())
   902             return l;
   903     }
   904 
   905     // :TODO: remove
   906     assert(*l == *r);
   907 
   908     return left->type();
   909 }
   910 
   911 HIR *
   912 SemanticAnalysis::typeCheckArray(const SourcePosition &pos,
   913                                  HIR *from,
   914                                  Handle<ArrayType> argActual,
   915                                  CoercionKind kind)
   916 {
   917     Local<Type> argGiven(zone_, from->type());
   918 
   919     // Special case: if we receive a string literal, and this is a char array,
   920     // we allow a coercion.
   921     if (from->isString() &&
   922         argGiven->isString() &&
   923         argActual->isArray() &&
   924         ArrayType::cast(argActual)->isCharArray())
   925     {
   926         HString *hir = from->toString();
   927         Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
   928 
   929         if (actual->isFixedLength()) {
   930             if (hir->string()->length() + 1 > actual->fixedLength()) {
   931                 cc_.reportError(pos, Message_ArrayAssignmentTooBig);
   932                 return NULL;
   933             }
   934         }
   935 
   936         // Transform the string literal into an array literal. We give it the
   937         // type of the left-hand side. The constness of the destination type
   938         // will determine whether HArray duplicates it or not.
   939         Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, actual));
   940         if (!map)
   941             return NULL;
   942 
   943         Local<Array> array(zone_);
   944         array = Array::NewString(zone_,
   945                                  map,
   946                                  hir->string()->chars(),
   947                                  hir->string()->length(),
   948                                  Heap::Tenure_Old);
   949         if (!array)
   950             return NULL;
   951 
   952         // Since we're creating a canonical copy of the char array, we have to
   953         // be careful that it doesn't get mutated. There are two cases where
   954         // we know it can't be mutated, and therefore don't need to specify
   955         // that it be cloned after pushing it onto the stack.
   956         //
   957         //  (1) The array type is const.
   958         //  (2) The array type is fixed-length, and the coercion is for
   959         //      assignment, meaning it will be immediately copied.
   960         //
   961         // We treat declaration separately from assignment, since for
   962         // declaration we can just immediately use the cloned version.
   963         bool shouldDuplicate = true;
   964         if ((actual->quals() & TypeQual_Const) ||
   965             (actual->isFixedLength() && kind == Coerce_Assign))
   966         {
   967             shouldDuplicate = false;
   968         }
   969 
   970         return new (pool_) HArray(hir->node(), actual, array, shouldDuplicate);
   971     }
   972 
   973     if (!argGiven->isArray()) {
   974         cc_.reportError(pos, Message_ExpectedArray);
   975         return NULL;
   976     }
   977 
   978     Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
   979     Local<ArrayType> given(zone_, ArrayType::cast(argGiven));
   980 
   981     if (actual->levels() != given->levels()) {
   982         cc_.reportError(pos, Message_ArrayDimensionsMismatch);
   983         return NULL;
   984     }
   985 
   986     unsigned level = 1;
   987     while (true) {
   988         if (actual->isFixedLength()) {
   989             if (!given->isFixedLength()) {
   990                 cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
   991                 return NULL;
   992             }
   993 
   994             if (actual->isCharArray()) {
   995                 // String assignment can have a truncated |given|.
   996                 if (given->fixedLength() > actual->fixedLength()) {
   997                     cc_.reportError(pos, Message_ArrayAssignmentTooBig);
   998                     return NULL;
   999                 }
  1000             } else {
  1001                 if (given->fixedLength() != actual->fixedLength()) {
  1002                     cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
  1003                     return NULL;
  1004                 }
  1005             }
  1006         } else if (given->isFixedLength()) {
  1007             // We do not allow assignments in the form:
  1008             //  [][] = [][Y]
  1009             //
  1010             // Otherwise, the following code could break the size guarantees
  1011             // of the right-hand side:
  1012             //
  1013             //  new x[][5];
  1014             //  new y[][];
  1015             //  new z[3];
  1016             //
  1017             //
  1018             //  y = x;
  1019             //  y[0] = z;
  1020             //
  1021             // Now |x[0]| contains a 3-length array.
  1022             if (level > 1) {
  1023                 cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
  1024                 return NULL;
  1025             }
  1026         }
  1027 
  1028         if (!given->contained()->isArray() || !actual->contained()->isArray())
  1029             break;
  1030 
  1031         given = ArrayType::cast(given->contained());
  1032         actual = ArrayType::cast(actual->contained());
  1033     }
  1034 
  1035     bool givenConst = !!(given->contained()->quals() & TypeQual_Const);
  1036     bool actualConst = !!(actual->contained()->quals() & TypeQual_Const);
  1037 
  1038     // These arrays must contain the same innermost type.
  1039     if (given->contained()->unqualified() != actual->contained()->unqualified() ||
  1040         (givenConst && !actualConst))
  1041     {
  1042         char aname[255];
  1043         char gname[255];
  1044         cc_.reportError(pos, Message_TypeMismatch,
  1045                         GetTypeName(argActual, aname, sizeof(aname)),
  1046                         GetTypeName(argGiven, gname, sizeof(gname)));
  1047         return NULL;
  1048     }
  1049 
  1050     return from;
  1051 }
  1052 
  1053 HIR *
  1054 SemanticAnalysis::typeFailure(const SourcePosition &pos, Handle<Type> from, Handle<Type> to)
  1055 {
  1056     char fname[255];
  1057     char tname[255];
  1058     cc_.reportError(pos, Message_InvalidCoercion,
  1059                     GetTypeName(from, fname, sizeof(fname)),
  1060                     GetTypeName(to, tname, sizeof(tname)));
  1061     return NULL;
  1062 }
  1063 
  1064 HIR *
  1065 SemanticAnalysis::coerce(HIR *hir, Handle<Type> to, CoercionKind kind)
  1066 {
  1067     Local<Type> from(zone_, hir->type());
  1068 
  1069     if (from->isInt32() && to->isFloat())
  1070         return new (pool_) HConvert(hir->node(), to, OP_CVT_I2F, hir);
  1071     if (from->isInt32() && to->isBool())
  1072         return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir);
  1073 
  1074     if (to->isEnum() && *from != to)
  1075         return typeFailure(hir->node()->pos(), from, to);
  1076     
  1077     if (to->isArray()) {
  1078         Local<ArrayType> atype(zone_, ArrayType::cast(to));
  1079         return typeCheckArray(hir->node()->pos(), hir, atype, kind);
  1080     }
  1081     
  1082     return hir;
  1083 }
  1084 
  1085 void
  1086 SemanticAnalysis::set(VariableSymbol *sym)
  1087 {
  1088     if (sym->scope()->kind() == Scope::GLOBAL) {
  1089         __ setglobal(sym);
  1090     } else {
  1091         assert(sym->storage() == VariableSymbol::Local);
  1092         __ setlocal(sym);
  1093     }
  1094 }
  1095 
  1096 HIR *
  1097 SemanticAnalysis::binary(AstNode *node, TokenKind token, HIR *left, HIR *right)
  1098 {
  1099     Local<Type> coercion(zone_, coercionType(token, left, right));
  1100     if (!coercion)
  1101         return NULL;
  1102     if ((left = coerce(left, coercion, Coerce_Arg)) == NULL)
  1103         return NULL;
  1104     if ((right = coerce(right, coercion, Coerce_Arg)) == NULL)
  1105         return NULL;
  1106     
  1107     switch (token) {
  1108      case TOK_PLUS:
  1109       case TOK_MINUS:
  1110       case TOK_STAR:
  1111       case TOK_SLASH:
  1112       case TOK_PERCENT:
  1113       case TOK_AMPERSAND:
  1114       case TOK_BITOR:
  1115       case TOK_BITXOR:
  1116       case TOK_SHR:
  1117       case TOK_USHR:
  1118       case TOK_SHL:
  1119         return new (pool_) HBinary(node, left->type(), token, left, right);
  1120 
  1121       case TOK_EQUALS:
  1122       case TOK_NOTEQUALS:
  1123       case TOK_LT:
  1124       case TOK_LE:
  1125       case TOK_GT:
  1126       case TOK_GE:
  1127       case TOK_AND:
  1128       case TOK_OR:
  1129       {
  1130         Local<Type> result(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
  1131         return new (pool_) HBinary(node, result, token, left, right);
  1132       }
  1133 
  1134       default:
  1135         assert(false);
  1136         return NULL;
  1137     }
  1138 }
  1139 
  1140 static inline bool
  1141 IsValidUncheckedType(Type *type)
  1142 {
  1143     return type->isEnum() ||
  1144            type->isFloat() ||
  1145            type->isInt32() ||
  1146            type->isChar() ||
  1147            type->isUnchecked() ||
  1148            type->isBool();
  1149 }
  1150 
  1151 void
  1152 SemanticAnalysis::visitUnaryExpression(UnaryExpression *node)
  1153 {
  1154     HIR *hir = eval(node->expression());
  1155     if (!hir)
  1156         return;
  1157 
  1158     switch (node->token()) {
  1159       case TOK_TILDE:
  1160       {
  1161         if (!hir->type()->isInt32() && !hir->type()->isEnum()) {
  1162             char name[255];
  1163             cc_.reportError(node->pos(), Message_InvalidUnaryType,
  1164                             "~",
  1165                             GetTypeName(hir->type(), name, sizeof(name)));
  1166         }
  1167         Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
  1168         hir_ = new (pool_) HUnary(node, hir->type(), TOK_TILDE, hir);
  1169         return;
  1170       }
  1171 
  1172       case TOK_MINUS:
  1173       {
  1174         if (hir->type()->isInt32() || hir->type()->isEnum()) {
  1175             Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
  1176             hir_ = new (pool_) HUnary(node, type, TOK_MINUS, hir);
  1177             return;
  1178         }
  1179         if (hir->type()->isFloat()) {
  1180             hir_ = new (pool_) HUnary(node, hir->type(), TOK_MINUS, hir);
  1181             return;
  1182         }
  1183 
  1184         char name[255];
  1185         cc_.reportError(node->pos(), Message_InvalidUnaryType,
  1186                         "-",
  1187                         GetTypeName(hir->type(), name, sizeof(name)));
  1188         break;
  1189       }
  1190 
  1191       default:
  1192       {
  1193         assert(node->token() == TOK_LABEL);
  1194 
  1195         TypeSymbol *sym = node->tag()->sym()->asType();
  1196         if (!sym) {
  1197             cc_.reportError(node->pos(), Message_IdentifierIsNotAType,
  1198                             sym->name()->chars());
  1199             return;
  1200         }
  1201 
  1202         if (!IsValidUncheckedType(sym->type())) {
  1203             char name[255];
  1204             cc_.reportError(node->pos(), Message_InvalidUncheckedCastTo,
  1205                             GetTypeName(hir->type(), name, sizeof(name)));
  1206             return;
  1207         }
  1208         if (!IsValidUncheckedType(hir->type())) {
  1209             char name[255];
  1210             cc_.reportError(node->pos(), Message_InvalidUncheckedCastFrom,
  1211                             GetTypeName(hir->type(), name, sizeof(name)));
  1212             return;
  1213         }
  1214 
  1215         hir_ = new (pool_) HUnary(node, hir->type(), TOK_LABEL, hir);
  1216         break;
  1217       }
  1218     }
  1219 }
  1220 
  1221 static inline TokenKind
  1222 ToCompare(Expression *expr)
  1223 {
  1224     if (expr->isBinaryExpression()) {
  1225         BinaryExpression *b = expr->toBinaryExpression();
  1226         if (b->token() >= TOK_EQUALS && b->token() <= TOK_OR)
  1227             return b->token();
  1228     } else if (expr->isUnaryExpression()) {
  1229         UnaryExpression *u = expr->toUnaryExpression();
  1230         if (u->token() == TOK_NOT)
  1231             return TOK_NOT;
  1232     }
  1233     return TOK_EOF;
  1234 }
  1235 
  1236 void
  1237 SemanticAnalysis::visitForTest(Expression *expr,
  1238                                Label *trueBranch,
  1239                                Label *falseBranch,
  1240                                Label *fallthrough)
  1241 {
  1242     Local<Type> boolType(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
  1243 
  1244     TokenKind token = ToCompare(expr);
  1245     if (token == TOK_EOF || token == TOK_NOT) {
  1246         HIR *hir;
  1247         if (token == TOK_EOF)
  1248             hir = eval(expr);
  1249         else
  1250             hir = eval(expr->toUnaryExpression()->expression());
  1251         if (!hir)
  1252             return;
  1253         if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
  1254             return;
  1255 
  1256         discharge(hir);
  1257 
  1258         bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
  1259         Opcode op = jumpOnTrue ? OP_JT : OP_JF;
  1260         
  1261         if (fallthrough == falseBranch)
  1262             __ j(op, trueBranch);
  1263         else
  1264             __ j(op, falseBranch);
  1265         return;
  1266     }
  1267 
  1268     BinaryExpression *bin = expr->toBinaryExpression();
  1269     if (token == TOK_AND || token == TOK_OR) {
  1270         Label next;
  1271         if (token == TOK_AND)
  1272             visitForTest(bin->left(), &next, falseBranch, &next);
  1273         else
  1274             visitForTest(bin->left(), trueBranch, &next, &next);
  1275         __ bind(&next);
  1276         visitForTest(bin->right(), trueBranch, falseBranch, fallthrough);
  1277         return;
  1278     }
  1279 
  1280     HIR *left = eval(bin->left());
  1281     HIR *right = eval(bin->right());
  1282     if (!left || !right)
  1283         return;
  1284 
  1285     HIR *hir = binary(bin, bin->token(), left, right);
  1286     if (!hir)
  1287         return;
  1288     if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
  1289         return;
  1290 
  1291     discharge(hir);
  1292     if (fallthrough == trueBranch)
  1293         __ j(OP_JF, falseBranch);
  1294     else
  1295         __ j(OP_JT, trueBranch);
  1296 }
  1297 
  1298 HLValue *
  1299 SemanticAnalysis::lvalue(Expression *expr)
  1300 {
  1301     HIR *hir = eval(expr);
  1302     if (!hir)
  1303         return NULL;
  1304     
  1305     if (!hir->isLValue()) {
  1306         cc_.reportError(expr->pos(), Message_ExpectedLValue);
  1307         return NULL;
  1308     }
  1309 
  1310     return static_cast<HLValue *>(hir);
  1311 }
  1312 
  1313 HIR *
  1314 SemanticAnalysis::eval(Expression *expr)
  1315 {
  1316     assert(!hir_);
  1317     expr->accept(this);
  1318 
  1319     HIR *hir = hir_;
  1320     hir_ = NULL;
  1321 
  1322     return hir;
  1323 }
  1324 
  1325 void
  1326 SemanticAnalysis::discharge(HIR *hir)
  1327 {
  1328     EmitHIR(zone_, emitter_, hir);
  1329 }