1.1 --- a/src/compiler/SemanticAnalysis.cpp Mon Jun 10 00:46:29 2013 +0100
1.2 +++ b/src/compiler/SemanticAnalysis.cpp Mon Jun 10 01:04:43 2013 +0100
1.3 @@ -1,1423 +1,1423 @@
1.4 -/* vim: set ts=4 sw=4 tw=99 et:
1.5 - *
1.6 - * Copyright (C) 2012 David Anderson
1.7 - *
1.8 - * This file is part of SourcePawn.
1.9 - *
1.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
1.11 - * the terms of the GNU General Public License as published by the Free
1.12 - * Software Foundation, either version 3 of the License, or (at your option)
1.13 - * any later version.
1.14 - *
1.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
1.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.18 - *
1.19 - * You should have received a copy of the GNU General Public License along with
1.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
1.21 - */
1.22 -#include <assert.h>
1.23 -#include "../Zone.h"
1.24 -#include "../Strings.h"
1.25 -#include "../NativeTable.h"
1.26 -#include "../TypeManager.h"
1.27 -#include "../Modules.h"
1.28 -#include "../Code.h"
1.29 -#include "SemanticAnalysis.h"
1.30 -#include "../Heap-inl.h"
1.31 -
1.32 -using namespace ke;
1.33 -
1.34 -#define __ emitter_.
1.35 -
1.36 -typedef BytecodeEmitter::Label Label;
1.37 -
1.38 -class AutoEnterScope
1.39 -{
1.40 - public:
1.41 - AutoEnterScope(Scope **prevp, Scope *scope)
1.42 - : prevp_(prevp),
1.43 - prev_(*prevp),
1.44 - scope_(scope)
1.45 - {
1.46 - if (!scope_)
1.47 - return;
1.48 - prev_ = *prevp_;
1.49 - *prevp_ = scope;
1.50 - assert(prev_ == scope->enclosing());
1.51 - }
1.52 - ~AutoEnterScope()
1.53 - {
1.54 - if (scope_)
1.55 - *prevp_ = prev_;
1.56 - }
1.57 - private:
1.58 - Scope **prevp_;
1.59 - Scope *prev_;
1.60 - Scope *scope_;
1.61 -};
1.62 -
1.63 -SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, TranslationUnit *unit)
1.64 - : zone_(zone),
1.65 - pool_(zone->pool()),
1.66 - cc_(cc),
1.67 - unit_(unit),
1.68 - hir_(NULL),
1.69 - loop_(NULL)
1.70 -{
1.71 -}
1.72 -
1.73 -SemanticAnalysis::SemanticAnalysis(SemanticAnalysis *parent, Handle<FunctionType> fun)
1.74 - : zone_(parent->zone_),
1.75 - pool_(parent->pool_),
1.76 - cc_(parent->cc_),
1.77 - unit_(parent->unit_),
1.78 - hir_(NULL),
1.79 - scope_(parent->scope_),
1.80 - fun_(fun),
1.81 - loop_(NULL),
1.82 - control_(NULL)
1.83 -{
1.84 -
1.85 -}
1.86 -
1.87 -void
1.88 -SemanticAnalysis::analyze()
1.89 -{
1.90 - scope_ = unit_->globalScope();
1.91 -
1.92 - for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
1.93 - Statement *stmt = unit_->tree()->statements()->at(i);
1.94 - stmt->accept(this);
1.95 - }
1.96 -
1.97 - Local<Code> code(zone_, __ finish());
1.98 - if (!code)
1.99 - return;
1.100 - code->setModule(unit_->module());
1.101 - unit_->module()->setCode(code);
1.102 -
1.103 -#ifndef NDEBUG
1.104 -// Disassemble(code, stdout);
1.105 -#endif
1.106 -}
1.107 -
1.108 -void
1.109 -SemanticAnalysis::visitFunctionStatement(FunctionStatement *stmt)
1.110 -{
1.111 - FunctionSymbol *sym = stmt->sym();
1.112 - Local<FunctionType> type(zone_, sym->type());
1.113 -
1.114 - assert(scope_->kind() == Scope::GLOBAL);
1.115 -
1.116 - if (stmt->token() == TOK_NATIVE) {
1.117 - // Define the native now.
1.118 - size_t index;
1.119 - if (!zone_->nativeTable()->add(stmt->name(), &index))
1.120 - return;
1.121 -
1.122 - Local<Native> native(zone_, Native::New(zone_, type, index));
1.123 - if (!native)
1.124 - return;
1.125 -
1.126 - __ object(native);
1.127 - __ setglobal(sym);
1.128 - __ pop();
1.129 - }
1.130 -
1.131 - // If the function is a forward or native, we don't have to do anything.
1.132 - if (stmt->token() == TOK_NATIVE || stmt->token() == TOK_FORWARD)
1.133 - return;
1.134 -
1.135 - SemanticAnalysis child(this, type);
1.136 - Local<Function> funobj(zone_, child.compile(stmt));
1.137 - if (!funobj)
1.138 - return;
1.139 -
1.140 - __ object(funobj);
1.141 - __ setglobal(sym);
1.142 - if (stmt->token() == TOK_PUBLIC)
1.143 - __ public_();
1.144 - else
1.145 - __ pop();
1.146 -}
1.147 -
1.148 -Function *
1.149 -SemanticAnalysis::compile(FunctionStatement *stmt)
1.150 -{
1.151 - __ setFirstLine(stmt->pos().line);
1.152 -
1.153 - AutoEnterScope argScope(&scope_, stmt->argScope());
1.154 -
1.155 - for (size_t i = 0; i < stmt->signature().parameters()->length(); i++) {
1.156 - Parameter *param = stmt->signature().parameters()->at(i);
1.157 - param->sym()->allocate(VariableSymbol::Arg, i);
1.158 - }
1.159 -
1.160 - AutoEnterScope varScope(&scope_, stmt->varScope());
1.161 - ControlStatus status = visitForControl(stmt->body());
1.162 -
1.163 - if (!fun_->returnType()->isVoid()) {
1.164 - // If the function is not void, report if not all paths return a value.
1.165 - // All other incorrect return cases have been caught already.
1.166 - if (status.returns() == Returns_Sometimes) {
1.167 - cc_.reportError(stmt->pos(), Message_NotAllPathsReturnValue);
1.168 - return NULL;
1.169 - }
1.170 -
1.171 - if (status.returns() == Returns_Never) {
1.172 - cc_.reportError(stmt->pos(), Message_MissingReturnValue);
1.173 - return NULL;
1.174 - }
1.175 - }
1.176 -
1.177 - Local<Code> code(zone_, __ finish());
1.178 - if (!code)
1.179 - return NULL;
1.180 - code->setModule(unit_->module());
1.181 -
1.182 - Local<Function> fun(zone_, Function::New(zone_, code, fun_, stmt->name(), stmt->pos()));
1.183 - if (!fun)
1.184 - return NULL;
1.185 -
1.186 -#ifndef NDEBUG
1.187 -// Disassemble(code, stdout);
1.188 -#endif
1.189 -
1.190 - return fun;
1.191 -}
1.192 -
1.193 -void
1.194 -SemanticAnalysis::visitBlockStatement(BlockStatement *node)
1.195 -{
1.196 - AutoEnterScope scope(&scope_, node->scope());
1.197 -
1.198 - for (size_t i = 0; i < node->statements()->length(); i++) {
1.199 - Statement *stmt = node->statements()->at(i);
1.200 - __ note_position(stmt->pos());
1.201 - stmt->accept(this);
1.202 - assert(__ stackDepth() == 0);
1.203 - }
1.204 -}
1.205 -
1.206 -void
1.207 -SemanticAnalysis::visitEnumStatement(EnumStatement *node)
1.208 -{
1.209 -}
1.210 -
1.211 -void
1.212 -SemanticAnalysis::visitExpressionStatement(ExpressionStatement *node)
1.213 -{
1.214 - // While building HIR, we enter new pool and root scopes, since HIR
1.215 - // creation is purely temporary.
1.216 - PoolScope poolScope(zone_->pool());
1.217 - RootScope rootScope(zone_);
1.218 -
1.219 - HIR *hir = eval(node->expression());
1.220 - if (!hir)
1.221 - return;
1.222 -
1.223 - discharge(hir);
1.224 - if (!hir->type()->isVoid())
1.225 - __ pop();
1.226 -}
1.227 -
1.228 -void
1.229 -SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
1.230 -{
1.231 - // If both sides terminate in a return, we consider this a return as well.
1.232 - if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
1.233 - terminate(Returns_Always);
1.234 - return;
1.235 - }
1.236 -
1.237 - ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
1.238 - ? Returns_Never
1.239 - : Returns_Sometimes;
1.240 -
1.241 - if (left.terminates() && right.terminates())
1.242 - terminate(status);
1.243 - else
1.244 - returns(status);
1.245 -}
1.246 -
1.247 -SemanticAnalysis::ControlStatus
1.248 -SemanticAnalysis::visitForControl(Statement *statement)
1.249 -{
1.250 - ControlScope scope(&control_);
1.251 - statement->accept(this);
1.252 - return scope.status();
1.253 -}
1.254 -
1.255 -void
1.256 -SemanticAnalysis::visitIfStatement(IfStatement *node)
1.257 -{
1.258 - Label join;
1.259 -
1.260 - ControlStatus trueBranch;
1.261 - ControlStatus falseBranch(false, Returns_Never);
1.262 -
1.263 - if (!node->ifFalse()) {
1.264 - Label success;
1.265 -
1.266 - visitForTest(node->condition(), &success, &join, &success);
1.267 - __ bind(&success);
1.268 - trueBranch = visitForControl(node->ifTrue());
1.269 - } else {
1.270 - Label success, next;
1.271 -
1.272 - visitForTest(node->condition(), &success, &next, &success);
1.273 - __ bind(&success);
1.274 - trueBranch = visitForControl(node->ifTrue());
1.275 - __ jump(&join);
1.276 - __ bind(&next);
1.277 - falseBranch = visitForControl(node->ifFalse());
1.278 - }
1.279 -
1.280 - __ bind(&join);
1.281 -
1.282 - control_->merge(trueBranch, falseBranch);
1.283 -}
1.284 -
1.285 -void
1.286 -SemanticAnalysis::requireLifoStack()
1.287 -{
1.288 - if (!loop_)
1.289 - return;
1.290 -
1.291 - loop_->setUsesLifoStack();
1.292 -}
1.293 -
1.294 -SemanticAnalysis::ControlStatus
1.295 -SemanticAnalysis::visitLoopBody(Statement *stmt)
1.296 -{
1.297 - // We always mark off a loop body, so on each edge, we can balance the
1.298 - // LIFO stack. Right now, we don't have the ability to budget the LIFO
1.299 - // stack ahead of time. If we turn out to never need the LIFO stack, we
1.300 - // mark it as unnecessary. (The interpreter can't really make use of this,
1.301 - // but the JIT can).
1.302 - //
1.303 - // Note that balancing the LIFO stack isn't even necessary, so this
1.304 - // feature may be removed. All this mechanism does is mitigate the
1.305 - // possibility that a long-running loop will overflow the LIFO region
1.306 - // and therefore start requiring nursery allocations.
1.307 - int pos = __ enterloop();
1.308 - ControlStatus status = visitForControl(stmt);
1.309 - __ leaveloop();
1.310 -
1.311 - if (loop_->usesLifoStack())
1.312 - __ setLoopUsesLifoStack(pos);
1.313 -
1.314 - return status;
1.315 -}
1.316 -
1.317 -void
1.318 -SemanticAnalysis::visitForStatement(ForStatement *node)
1.319 -{
1.320 - AutoEnterScope scope(&scope_, node->scope());
1.321 - PoolScope poolScope(zone_->pool());
1.322 - RootScope rootScope(zone_);
1.323 -
1.324 - Label join, update;
1.325 - LoopScope loop(scope_, &join, &update, &loop_);
1.326 -
1.327 - if (node->initialization())
1.328 - node->initialization()->accept(this);
1.329 -
1.330 - Label header, test;
1.331 - if (node->condition())
1.332 - __ jump(&test);
1.333 -
1.334 - __ bind(&header);
1.335 - ControlStatus status = visitLoopBody(node->body());
1.336 -
1.337 - __ bind(&update);
1.338 - if (node->update())
1.339 - node->update()->accept(this);
1.340 -
1.341 - if (node->condition()) {
1.342 - __ bind(&test);
1.343 - visitForTest(node->condition(), &header, &join, &join);
1.344 - } else {
1.345 - __ jump(&header);
1.346 - }
1.347 -
1.348 - __ bind(&join);
1.349 -
1.350 - // If there was a condition, we treat this like a while loop. Otherwise,
1.351 - // the join point is only reachable if the loop contains a break. The
1.352 - // termination status doesn't tell us anything yet.
1.353 - if (node->condition() || loop.breaks())
1.354 - control_->merge(status, ControlStatus(false, Returns_Never));
1.355 - else
1.356 - control_->terminate(status.returns());
1.357 -
1.358 - assert(__ stackDepth() == 0);
1.359 -}
1.360 -
1.361 -void
1.362 -SemanticAnalysis::visitWhileStatement(WhileStatement *node)
1.363 -{
1.364 - PoolScope poolScope(zone_->pool());
1.365 - RootScope rootScope(zone_);
1.366 -
1.367 - Label header, join;
1.368 -
1.369 - __ bind(&header);
1.370 -
1.371 - ControlStatus status;
1.372 -
1.373 - LoopScope loop(scope_, &join, &header, &loop_);
1.374 - if (node->token() == TOK_WHILE) {
1.375 - Label body;
1.376 - visitForTest(node->condition(), &body, &join, &body);
1.377 - status = visitLoopBody(node->body());
1.378 - __ jump(&header);
1.379 - } else {
1.380 - status = visitLoopBody(node->body());
1.381 - visitForTest(node->condition(), &header, &join, &join);
1.382 - }
1.383 -
1.384 - __ bind(&join);
1.385 -
1.386 - // Detect loops that will always have a fork in the contro-flow graph.
1.387 - // This will be a |while| loop, or a |do-while| loop whose body does
1.388 - // not terminate. For now, we treat these as an |if| regardless of the
1.389 - // direction the branch can take. That means the control-flow is always
1.390 - // conditional.
1.391 - if (node->token() == TOK_WHILE || status.terminates() || loop.breaks()) {
1.392 - control_->merge(status, ControlStatus(false, Returns_Never));
1.393 - } else {
1.394 - // At this point, we've got a do-while loop with a |return| or
1.395 - // |continue|, meaning that the rest of the block is unreachable.
1.396 - control_->terminate(status.returns());
1.397 - }
1.398 -
1.399 - assert(__ stackDepth() == 0);
1.400 -}
1.401 -
1.402 -static inline Heap::Tenure
1.403 -InferTenure(Symbol *sym)
1.404 -{
1.405 - if (sym->scope()->kind() == Scope::GLOBAL)
1.406 - return Heap::Tenure_Old;
1.407 -
1.408 - // SP2's array semantics allow any array kind to escape, so we must use
1.409 - // the normal heap. (Hopefully escape analysis can ease this pain later).
1.410 - if (sym->type()->isArray())
1.411 - return Heap::Tenure_Default;
1.412 -
1.413 - return Heap::Tenure_Default;
1.414 -}
1.415 -
1.416 -void
1.417 -SemanticAnalysis::visitVariableDeclaration(VariableDeclaration *node)
1.418 -{
1.419 - PoolScope poolScope(zone_->pool());
1.420 - RootScope rootScope(zone_);
1.421 -
1.422 - Local<Type> type(zone_, node->sym()->type());
1.423 -
1.424 - if (node->sym()->type()->isVoid()) {
1.425 - cc_.reportError(node->type()->pos(), Message_CannotDeclareVoid);
1.426 - return;
1.427 - }
1.428 -
1.429 - if (node->initialization()) {
1.430 - HIR *hir = NULL;
1.431 -
1.432 - if ((hir = eval(node->initialization())) == NULL)
1.433 - return;
1.434 - if ((hir = coerce(hir, type, Coerce_Decl)) == NULL)
1.435 - return;
1.436 -
1.437 - discharge(hir);
1.438 - } else {
1.439 - if (type->isInt32() || type->isEnum() ||
1.440 - type->isChar() || type->isBool())
1.441 - {
1.442 - __ int_(0);
1.443 - } else if (type->isFloat()) {
1.444 - __ float_(0);
1.445 - } else if (type->isArray()) {
1.446 - Local<ArrayType> atype(zone_, ArrayType::cast(type));
1.447 - Local<ArrayMap> map(zone_, atype->newMap());
1.448 - if (!map)
1.449 - return;
1.450 -
1.451 - if (atype->isFixedLength()) {
1.452 - __ newarray(OP_NEWFIXED, map, InferTenure(node->sym()));
1.453 - } else if (node->dims()->at(0)) {
1.454 - // This may not be true if we allow typedefing, so :TODO:
1.455 - // figure out proper semantics.
1.456 - assert(node->dims()->length() == atype->levels());
1.457 -
1.458 - Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.459 - for (size_t i = 0; i < node->dims()->length(); i++) {
1.460 - Expression *expr = node->dims()->at(i);
1.461 - if (expr) {
1.462 - HIR *hir = eval(expr);
1.463 - if (!hir || ((hir = coerce(hir, i32, Coerce_Arg)) == NULL))
1.464 - return;
1.465 - discharge(hir);
1.466 - } else {
1.467 - __ int_(0);
1.468 - }
1.469 - }
1.470 - __ newarray(OP_NEWSIZED, map, InferTenure(node->sym()));
1.471 - } else {
1.472 - __ newarray(OP_NEWEMPTY, map, InferTenure(node->sym()));
1.473 - }
1.474 - } else {
1.475 - assert(false);
1.476 - }
1.477 - }
1.478 -
1.479 - if (node->sym()->scope()->kind() != Scope::GLOBAL) {
1.480 - if (!__ allocate(node->sym()))
1.481 - return;
1.482 - }
1.483 -
1.484 - set(node->sym());
1.485 - __ pop();
1.486 -}
1.487 -
1.488 -void
1.489 -SemanticAnalysis::visitReturnStatement(ReturnStatement *node)
1.490 -{
1.491 - control_->returns(Returns_Always);
1.492 -
1.493 - if (!node->expression()) {
1.494 - if (!fun_->returnType()->isVoid()) {
1.495 - cc_.reportError(node->pos(), Message_MissingReturnValue);
1.496 - return;
1.497 - }
1.498 -
1.499 - __ returnvoid();
1.500 - return;
1.501 - }
1.502 -
1.503 - if (fun_->returnType()->isVoid()) {
1.504 - cc_.reportError(node->pos(), Message_UsedVoidReturn);
1.505 - return;
1.506 - }
1.507 -
1.508 - PoolScope poolScope(zone_->pool());
1.509 - RootScope rootScope(zone_);
1.510 -
1.511 - HIR *hir = eval(node->expression());
1.512 - if (!hir)
1.513 - return;
1.514 -
1.515 - Local<Type> returnType(zone_, fun_->returnType());
1.516 - if ((hir = coerce(hir, returnType, Coerce_Return)) == NULL)
1.517 - return;
1.518 -
1.519 - discharge(hir);
1.520 -
1.521 - if (hir->type()->isVoid())
1.522 - __ returnvoid();
1.523 - else
1.524 - __ return_();
1.525 -}
1.526 -
1.527 -void
1.528 -SemanticAnalysis::visitBinaryExpression(BinaryExpression *node)
1.529 -{
1.530 - HIR *left = eval(node->left());
1.531 - HIR *right = eval(node->right());
1.532 - if (!left || !right)
1.533 - return;
1.534 -
1.535 - hir_ = binary(node, node->token(), left, right);
1.536 -}
1.537 -
1.538 -bool
1.539 -SemanticAnalysis::checkArgumentCount(Handle<FunctionType> type, unsigned actual)
1.540 -{
1.541 - if (type->parameters()->length() == actual)
1.542 - return true;
1.543 -
1.544 - if (actual > type->parameters()->length()) {
1.545 - if (!type->isNative() || !type->isNativeVariadic())
1.546 - return false;
1.547 - return true;
1.548 - }
1.549 -
1.550 - if (!type->defaults())
1.551 - return false;
1.552 -
1.553 - // Missing arguments. See if there's a default argument for each missing
1.554 - // actual.
1.555 - for (unsigned i = actual; i < type->parameters()->length(); i++) {
1.556 - if (!type->defaults()->at(i))
1.557 - return false;
1.558 - }
1.559 -
1.560 - return true;
1.561 -}
1.562 -
1.563 -static unsigned
1.564 -BindImplicitName(Module *from, ImplicitSymbol *sym)
1.565 -{
1.566 - if (sym->bound())
1.567 - return sym->fieldIndex();
1.568 -
1.569 - Module *module = Module::cast(from->getImportAt(sym->index()));
1.570 - StructMap *map = module->globals()->map();
1.571 -
1.572 - unsigned fieldIndex;
1.573 - Descriptor *desc = map->type()->lookupField(sym->name(), &fieldIndex);
1.574 - assert(desc && desc->type() == sym->type());
1.575 -
1.576 - sym->bind(fieldIndex);
1.577 - return fieldIndex;
1.578 -}
1.579 -
1.580 -void
1.581 -SemanticAnalysis::visitNameProxy(NameProxy *proxy)
1.582 -{
1.583 - Symbol *sym = proxy->sym();
1.584 -
1.585 - switch (sym->kind()) {
1.586 - case Symbol::kImport:
1.587 - {
1.588 - ImportSymbol *import = sym->toImport();
1.589 - hir_ = new (pool_) HImport(proxy, sym->type(), import->index());
1.590 - break;
1.591 - }
1.592 -
1.593 - case Symbol::kImplicit:
1.594 - {
1.595 - ImplicitSymbol *import = sym->toImplicit();
1.596 - unsigned fieldIndex = BindImplicitName(unit_->module(), import);
1.597 -
1.598 - hir_ = new (pool_) HImport(proxy, zone_->types()->getImportable(), import->index());
1.599 - hir_ = new (pool_) HField(proxy, hir_, sym->type(), fieldIndex);
1.600 - break;
1.601 - }
1.602 -
1.603 - case Symbol::kConstant:
1.604 - {
1.605 - ConstantSymbol *val = sym->toConstant();
1.606 - hir_ = new (pool_) HInteger(proxy, sym->type(), val->value().toInt());
1.607 - break;
1.608 - }
1.609 -
1.610 - // This is kind of screwy. Symbol::kFunction is like a constant we can't
1.611 - // evaluate yet. Maybe we should extract the GLOBAL case and say that
1.612 - // kFunction is only used for global functions (and use const vars for
1.613 - // local functions).
1.614 - case Symbol::kFunction:
1.615 - case Symbol::kVariable:
1.616 - {
1.617 - Scope *in = sym->scope();
1.618 - switch (in->kind()) {
1.619 - case Scope::GLOBAL:
1.620 - hir_ = new (pool_) HGlobal(proxy, sym);
1.621 - break;
1.622 -
1.623 - case Scope::FUNCTION:
1.624 - {
1.625 - VariableSymbol *var = sym->toVariable();
1.626 - assert(var->storage() == VariableSymbol::Arg);
1.627 - hir_ = new (pool_) HLocal(proxy, var);
1.628 - break;
1.629 - }
1.630 -
1.631 - default:
1.632 - {
1.633 - VariableSymbol *var = sym->toVariable();
1.634 - assert(in->kind() == Scope::BLOCK);
1.635 - assert(var->storage() == VariableSymbol::Local);
1.636 - hir_ = new (pool_) HLocal(proxy, var);
1.637 - break;
1.638 - }
1.639 - }
1.640 - break;
1.641 - }
1.642 -
1.643 - default:
1.644 - // :TODO:
1.645 - assert(false);
1.646 - }
1.647 -}
1.648 -
1.649 -void
1.650 -SemanticAnalysis::visitBooleanLiteral(BooleanLiteral *node)
1.651 -{
1.652 - Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
1.653 - hir_ = new (pool_) HBoolean(node, type, node->token() == TOK_TRUE);
1.654 -}
1.655 -
1.656 -void
1.657 -SemanticAnalysis::visitIntegerLiteral(IntegerLiteral *lit)
1.658 -{
1.659 - Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.660 - hir_ = new (pool_) HInteger(lit, type, lit->value());
1.661 -}
1.662 -
1.663 -void
1.664 -SemanticAnalysis::visitFloatLiteral(FloatLiteral *node)
1.665 -{
1.666 - Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
1.667 - hir_ = new (pool_) HFloat(node, type, (float)node->value());
1.668 -}
1.669 -
1.670 -void
1.671 -SemanticAnalysis::visitStringLiteral(StringLiteral *node)
1.672 -{
1.673 - Type *type = zone_->types()->getString();
1.674 - hir_ = new (pool_) HString(node, type, node->string());
1.675 -}
1.676 -
1.677 -void
1.678 -SemanticAnalysis::visitCallExpression(CallExpression *node)
1.679 -{
1.680 - HIR *callee = eval(node->callee());
1.681 - if (!callee)
1.682 - return;
1.683 -
1.684 - if (!callee->type()->isFunction()) {
1.685 - cc_.reportError(node->pos(), Message_CalleeNotFunction);
1.686 - return;
1.687 - }
1.688 -
1.689 - Local<FunctionType> fun(zone_, FunctionType::cast(callee->type()));
1.690 -
1.691 - if (!checkArgumentCount(fun, node->arguments()->length())) {
1.692 - cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
1.693 - return;
1.694 - }
1.695 -
1.696 - if (fun->isForward()) {
1.697 - cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
1.698 - return;
1.699 - }
1.700 -
1.701 - HIRList *args = new (pool_) HIRList;
1.702 - for (unsigned i = 0; i < node->arguments()->length(); i++) {
1.703 - Expression *expression = node->arguments()->at(i);
1.704 - HIR *arg = eval(expression);
1.705 - if (!arg)
1.706 - return;
1.707 -
1.708 - Handle<Type> given = arg->type();
1.709 -
1.710 - bool mustComputeReference;
1.711 - if (i >= fun->parameters()->length()) {
1.712 - // Special handling for natives. Arguments past the formal must
1.713 - // always have references computed. However, arrays are already
1.714 - // references for natives.
1.715 - assert(fun->isNative() && fun->isNativeVariadic());
1.716 - mustComputeReference = !given->isReference() &&
1.717 - !given->isArray();
1.718 - } else {
1.719 - Local<Type> actual(zone_, fun->parameterAt(i));
1.720 -
1.721 - if (expression->isIndexExpression() && arg->isIndex()) {
1.722 - // If the expression is the form x[y], and this produced a
1.723 - // normal array indexing operation, then we apply some
1.724 - // special rules.
1.725 -
1.726 - if (actual->isReference()) {
1.727 - // Disabled, since this doesn't have easily definable or
1.728 - // sensible semantics with SP2 arrays, but we don't want
1.729 - // to silently break SP1 semantics.
1.730 - cc_.reportError(expression->pos(), Message_CannotComputeIndexRef);
1.731 - return;
1.732 - }
1.733 -
1.734 - // As a special rule to account for SP1 semantics, we allow x[y]
1.735 - // to automatically compute a sliced, read-only array view if
1.736 - // the desired type is an array of one more dimension than x[y]
1.737 - // would return.
1.738 - //
1.739 - // As an additional restriction, this is only allowed for
1.740 - // one-level char arrays, to minimize potential issues until
1.741 - // we determine whether more compatibility is needed.
1.742 - //
1.743 - // Internally, for sanity, the dependent array operation does
1.744 - // not necessarily create a dependent array. For extensible
1.745 - // arrays, we instead create a duplicate arrary of just the
1.746 - // sliced portion, rather than deal with the complexity of the
1.747 - // source array being resized.
1.748 - //
1.749 - // Note that we don't really know whether a dependent array
1.750 - // will be dependent at compile-time, so the dependent type's
1.751 - // just inherits from the source.
1.752 - if (actual->isArray()) {
1.753 - HIndex *index = arg->toIndex();
1.754 - Local<ArrayType> basetype(zone_, ArrayType::cast(index->base()->type()));
1.755 - Local<ArrayType> atype(zone_, ArrayType::cast(actual));
1.756 -
1.757 - if (atype->isCharArray() && basetype->isCharArray()) {
1.758 - // There is no possible way this will type check, so
1.759 - // it's safe to just try something completely
1.760 - // different.
1.761 - Local<Type> slicetype(zone_);
1.762 - if (basetype->isFixedLength()) {
1.763 - // If the base type is fixed length, we need to
1.764 - // compute a new dynamic array type based on the
1.765 - // fixed array's contents and qualifiers.
1.766 - Local<Type> contained(zone_, basetype->contained());
1.767 - slicetype = zone_->types()->newArray(contained, ArrayType::DYNAMIC_ARRAY_SIZE);
1.768 - if (!slicetype)
1.769 - return;
1.770 - slicetype = zone_->types()->qualify(slicetype, basetype->quals());
1.771 - if (!slicetype)
1.772 - return;
1.773 - } else {
1.774 - slicetype = basetype;
1.775 - }
1.776 - arg = new (pool_) HNewDependentArray(expression, slicetype, index->base(), index->index());
1.777 - given = arg->type();
1.778 - }
1.779 - }
1.780 - }
1.781 -
1.782 - if (actual->isReference()) {
1.783 - // If the actual is a reference, the coercion rules are much
1.784 - // stricter; the contained types must be identical.
1.785 - // :TODO: make this not an assert
1.786 - assert(ReferenceType::cast(actual)->contained() == arg->type());
1.787 - } else {
1.788 - // When we start overloading, coercion will have to happen later.
1.789 - arg = coerce(arg, actual, Coerce_Arg);
1.790 - if (!arg)
1.791 - return;
1.792 - }
1.793 -
1.794 - mustComputeReference = actual->isReference() && !given->isReference();
1.795 - }
1.796 -
1.797 - if (mustComputeReference) {
1.798 - // Refs always use the LIFO stack if they can.
1.799 - arg = new (pool_) HToRef(arg->node(), arg->type(), arg);
1.800 - requireLifoStack();
1.801 - }
1.802 -
1.803 - if (!args->append(arg))
1.804 - return;
1.805 - }
1.806 -
1.807 - hir_ = new (pool_) HCall(node, fun->returnType(), callee, args);
1.808 -}
1.809 -
1.810 -void
1.811 -SemanticAnalysis::visitAssignment(Assignment *node)
1.812 -{
1.813 - HLValue *lval = lvalue(node->lvalue());
1.814 - if (!lval)
1.815 - return;
1.816 -
1.817 - if (lval->type()->quals() & TypeQual_Const) {
1.818 - cc_.reportError(node->pos(), Message_CannotModifyConst);
1.819 - return;
1.820 - }
1.821 -
1.822 - HIR *hir = eval(node->expression());
1.823 - if (!hir)
1.824 - return;
1.825 - if ((hir = coerce(hir, lval->type(), Coerce_Assign)) == NULL)
1.826 - return;
1.827 -
1.828 - hir_ = new (pool_) HStore(node, node->token(), lval, hir);
1.829 -}
1.830 -
1.831 -void
1.832 -SemanticAnalysis::visitBreakStatement(BreakStatement *node)
1.833 -{
1.834 - if (!loop_) {
1.835 - cc_.reportError(node->pos(), Message_BreakOutsideLoop);
1.836 - return;
1.837 - }
1.838 -
1.839 - loop_->setBreaks();
1.840 - __ j(OP_BREAK, loop_->break_());
1.841 -}
1.842 -
1.843 -void
1.844 -SemanticAnalysis::visitContinueStatement(ContinueStatement *node)
1.845 -{
1.846 - if (!loop_) {
1.847 - cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
1.848 - return;
1.849 - }
1.850 -
1.851 - __ j(OP_CONTINUE, loop_->continue_());
1.852 -}
1.853 -
1.854 -void
1.855 -SemanticAnalysis::visitIndexExpression(IndexExpression *node)
1.856 -{
1.857 - HIR *left = eval(node->left());
1.858 - if (!left)
1.859 - return;
1.860 -
1.861 - HIR *right = eval(node->right());
1.862 - if (!right)
1.863 - return;
1.864 -
1.865 - // Hrm... yes, for now, let's coerce here.
1.866 - Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.867 - if ((right = coerce(right, i32, Coerce_Arg)) == NULL)
1.868 - return;
1.869 -
1.870 - // Do not coerce here, there's no reason to yet.
1.871 - if (!left->type()->isArray()) {
1.872 - cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
1.873 - return;
1.874 - }
1.875 -
1.876 - hir_ = new (pool_) HIndex(node,
1.877 - ArrayType::cast(left->type())->contained(),
1.878 - left,
1.879 - right);
1.880 -}
1.881 -
1.882 -void
1.883 -SemanticAnalysis::visitIncDecExpression(IncDecExpression *node)
1.884 -{
1.885 - HLValue *lval = lvalue(node->expression());
1.886 - if (!lval)
1.887 - return;
1.888 -
1.889 - if (!lval->type()->isInt32() && !lval->type()->isFloat()) {
1.890 - assert(false);
1.891 - return;
1.892 - }
1.893 -
1.894 - HIR *rval;
1.895 - if (lval->type()->isInt32())
1.896 - rval = new (pool_) HInteger(node, lval->type(), 1);
1.897 - else
1.898 - rval = new (pool_) HFloat(node, lval->type(), 1.0);
1.899 -
1.900 - if (node->postfix())
1.901 - hir_ = new (pool_) HPostIncDec(node, node->token(), lval, rval);
1.902 - else
1.903 - hir_ = new (pool_) HStore(node, node->token(), lval, rval);
1.904 -}
1.905 -
1.906 -Type *
1.907 -SemanticAnalysis::coercionType(TokenKind token, HIR *left, HIR *right)
1.908 -{
1.909 - Local<Type> l(zone_, left->type());
1.910 - Local<Type> r(zone_, right->type());
1.911 -
1.912 - if (l->isPod())
1.913 - l = l->unqualified();
1.914 - if (r->isPod())
1.915 - r = r->unqualified();
1.916 -
1.917 - if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
1.918 - (token >= TOK_EQUALS && token <= TOK_GE))
1.919 - {
1.920 - // We allow: [float|int32] + [float|int32]
1.921 - if (l->isFloat() && r->isInt32())
1.922 - return l;
1.923 - if (l->isInt32() && r->isFloat())
1.924 - return r;
1.925 - if (l->isInt32() && r->isInt32())
1.926 - return l;
1.927 -
1.928 - if (l->isChar() && r->isInt32())
1.929 - return r;
1.930 - if (l->isInt32() && r->isChar())
1.931 - return l;
1.932 - }
1.933 -
1.934 - // :TODO: remove
1.935 - assert(*l == *r);
1.936 -
1.937 - return left->type();
1.938 -}
1.939 -
1.940 -HIR *
1.941 -SemanticAnalysis::typeCheckArray(const SourcePosition &pos,
1.942 - HIR *from,
1.943 - Handle<ArrayType> argActual,
1.944 - CoercionKind kind)
1.945 -{
1.946 - Local<Type> argGiven(zone_, from->type());
1.947 -
1.948 - // Special case: if we receive a string literal, and this is a char array,
1.949 - // we allow a coercion.
1.950 - if (from->isString() &&
1.951 - argGiven->isString() &&
1.952 - argActual->isArray() &&
1.953 - ArrayType::cast(argActual)->isCharArray())
1.954 - {
1.955 - HString *hir = from->toString();
1.956 - Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
1.957 -
1.958 - if (actual->isFixedLength()) {
1.959 - if (hir->string()->length() + 1 > actual->fixedLength()) {
1.960 - cc_.reportError(pos, Message_ArrayAssignmentTooBig);
1.961 - return NULL;
1.962 - }
1.963 - }
1.964 -
1.965 - // Transform the string literal into an array literal. We give it the
1.966 - // type of the left-hand side. The constness of the destination type
1.967 - // will determine whether HArray duplicates it or not.
1.968 - Local<ArrayMap> map(zone_, actual->newMap());
1.969 - if (!map)
1.970 - return NULL;
1.971 -
1.972 - Local<Array> array(zone_);
1.973 - array = Array::NewString(zone_,
1.974 - map,
1.975 - hir->string()->chars(),
1.976 - hir->string()->length(),
1.977 - Heap::Tenure_Old);
1.978 - if (!array)
1.979 - return NULL;
1.980 -
1.981 - // Since we're creating a canonical copy of the char array, we have to
1.982 - // be careful that it doesn't get mutated. There are two cases where
1.983 - // we know it can't be mutated, and therefore don't need to specify
1.984 - // that it be cloned after pushing it onto the stack.
1.985 - //
1.986 - // (1) The array type is const.
1.987 - // (2) The array type is fixed-length, and the coercion is for
1.988 - // assignment, meaning it will be immediately copied.
1.989 - //
1.990 - // We treat declaration separately from assignment, since for
1.991 - // declaration we can just immediately use the cloned version.
1.992 - bool shouldDuplicate = true;
1.993 - if ((actual->quals() & TypeQual_Const) ||
1.994 - (actual->isFixedLength() && kind == Coerce_Assign))
1.995 - {
1.996 - shouldDuplicate = false;
1.997 - }
1.998 -
1.999 - return new (pool_) HArray(hir->node(), actual, array, shouldDuplicate);
1.1000 - }
1.1001 -
1.1002 - if (!argGiven->isArray()) {
1.1003 - cc_.reportError(pos, Message_ExpectedArray);
1.1004 - return NULL;
1.1005 - }
1.1006 -
1.1007 - Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
1.1008 - Local<ArrayType> given(zone_, ArrayType::cast(argGiven));
1.1009 -
1.1010 - if (actual->levels() != given->levels()) {
1.1011 - cc_.reportError(pos, Message_ArrayDimensionsMismatch);
1.1012 - return NULL;
1.1013 - }
1.1014 -
1.1015 - unsigned level = 1;
1.1016 - while (true) {
1.1017 - if (actual->isFixedLength()) {
1.1018 - if (!given->isFixedLength()) {
1.1019 - cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.1020 - return NULL;
1.1021 - }
1.1022 -
1.1023 - if (actual->isCharArray()) {
1.1024 - // String assignment can have a truncated |given|.
1.1025 - if (given->fixedLength() > actual->fixedLength()) {
1.1026 - cc_.reportError(pos, Message_ArrayAssignmentTooBig);
1.1027 - return NULL;
1.1028 - }
1.1029 - } else {
1.1030 - if (given->fixedLength() != actual->fixedLength()) {
1.1031 - cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.1032 - return NULL;
1.1033 - }
1.1034 - }
1.1035 - } else if (given->isFixedLength()) {
1.1036 - // We do not allow assignments in the form:
1.1037 - // [][] = [][Y]
1.1038 - //
1.1039 - // Otherwise, the following code could break the size guarantees
1.1040 - // of the right-hand side:
1.1041 - //
1.1042 - // new x[][5];
1.1043 - // new y[][];
1.1044 - // new z[3];
1.1045 - //
1.1046 - //
1.1047 - // y = x;
1.1048 - // y[0] = z;
1.1049 - //
1.1050 - // Now |x[0]| contains a 3-length array.
1.1051 - if (level > 1) {
1.1052 - cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.1053 - return NULL;
1.1054 - }
1.1055 - }
1.1056 -
1.1057 - if (!given->contained()->isArray() || !actual->contained()->isArray())
1.1058 - break;
1.1059 -
1.1060 - given = ArrayType::cast(given->contained());
1.1061 - actual = ArrayType::cast(actual->contained());
1.1062 - }
1.1063 -
1.1064 - bool givenConst = !!(given->contained()->quals() & TypeQual_Const);
1.1065 - bool actualConst = !!(actual->contained()->quals() & TypeQual_Const);
1.1066 -
1.1067 - // These arrays must contain the same innermost type.
1.1068 - if (given->contained()->unqualified() != actual->contained()->unqualified() ||
1.1069 - (givenConst && !actualConst))
1.1070 - {
1.1071 - char aname[255];
1.1072 - char gname[255];
1.1073 - cc_.reportError(pos, Message_TypeMismatch,
1.1074 - GetTypeName(argActual, aname, sizeof(aname)),
1.1075 - GetTypeName(argGiven, gname, sizeof(gname)));
1.1076 - return NULL;
1.1077 - }
1.1078 -
1.1079 - return from;
1.1080 -}
1.1081 -
1.1082 -HIR *
1.1083 -SemanticAnalysis::typeFailure(const SourcePosition &pos, Handle<Type> from, Handle<Type> to)
1.1084 -{
1.1085 - char fname[255];
1.1086 - char tname[255];
1.1087 - cc_.reportError(pos, Message_InvalidCoercion,
1.1088 - GetTypeName(from, fname, sizeof(fname)),
1.1089 - GetTypeName(to, tname, sizeof(tname)));
1.1090 - return NULL;
1.1091 -}
1.1092 -
1.1093 -HIR *
1.1094 -SemanticAnalysis::coerce(HIR *hir, Handle<Type> to, CoercionKind kind)
1.1095 -{
1.1096 - Local<Type> from(zone_, hir->type());
1.1097 -
1.1098 - // If the source is *ever* an importable, we just fail.
1.1099 - if (from->isImportable())
1.1100 - return typeFailure(hir->node()->pos(), from, to);
1.1101 -
1.1102 - if (from->isInt32() && to->isFloat())
1.1103 - return new (pool_) HConvert(hir->node(), to, OP_CVT_I2F, hir);
1.1104 - if (from->isInt32() && to->isBool())
1.1105 - return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir);
1.1106 -
1.1107 - if (to->isEnum() && from->unqualified() != to->unqualified())
1.1108 - return typeFailure(hir->node()->pos(), from, to);
1.1109 -
1.1110 - if (to->isArray()) {
1.1111 - Local<ArrayType> atype(zone_, ArrayType::cast(to));
1.1112 - return typeCheckArray(hir->node()->pos(), hir, atype, kind);
1.1113 - }
1.1114 -
1.1115 - return hir;
1.1116 -}
1.1117 -
1.1118 -void
1.1119 -SemanticAnalysis::set(VariableSymbol *sym)
1.1120 -{
1.1121 - if (sym->scope()->kind() == Scope::GLOBAL) {
1.1122 - __ setglobal(sym);
1.1123 - } else {
1.1124 - assert(sym->storage() == VariableSymbol::Local);
1.1125 - __ setlocal(sym);
1.1126 - }
1.1127 -}
1.1128 -
1.1129 -HIR *
1.1130 -SemanticAnalysis::binary(AstNode *node, TokenKind token, HIR *left, HIR *right)
1.1131 -{
1.1132 - Local<Type> coercion(zone_, coercionType(token, left, right));
1.1133 - if (!coercion)
1.1134 - return NULL;
1.1135 - if ((left = coerce(left, coercion, Coerce_Arg)) == NULL)
1.1136 - return NULL;
1.1137 - if ((right = coerce(right, coercion, Coerce_Arg)) == NULL)
1.1138 - return NULL;
1.1139 -
1.1140 - switch (token) {
1.1141 - case TOK_PLUS:
1.1142 - case TOK_MINUS:
1.1143 - case TOK_STAR:
1.1144 - case TOK_SLASH:
1.1145 - case TOK_PERCENT:
1.1146 - case TOK_AMPERSAND:
1.1147 - case TOK_BITOR:
1.1148 - case TOK_BITXOR:
1.1149 - case TOK_SHR:
1.1150 - case TOK_USHR:
1.1151 - case TOK_SHL:
1.1152 - return new (pool_) HBinary(node, left->type(), token, left, right);
1.1153 -
1.1154 - case TOK_EQUALS:
1.1155 - case TOK_NOTEQUALS:
1.1156 - case TOK_LT:
1.1157 - case TOK_LE:
1.1158 - case TOK_GT:
1.1159 - case TOK_GE:
1.1160 - case TOK_AND:
1.1161 - case TOK_OR:
1.1162 - {
1.1163 - Local<Type> result(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
1.1164 - return new (pool_) HBinary(node, result, token, left, right);
1.1165 - }
1.1166 -
1.1167 - default:
1.1168 - assert(false);
1.1169 - return NULL;
1.1170 - }
1.1171 -}
1.1172 -
1.1173 -static inline bool
1.1174 -IsValidUncheckedType(Type *type)
1.1175 -{
1.1176 - return type->isEnum() ||
1.1177 - type->isFloat() ||
1.1178 - type->isInt32() ||
1.1179 - type->isChar() ||
1.1180 - type->isUnchecked() ||
1.1181 - type->isBool();
1.1182 -}
1.1183 -
1.1184 -void
1.1185 -SemanticAnalysis::visitUnaryExpression(UnaryExpression *node)
1.1186 -{
1.1187 - HIR *hir = eval(node->expression());
1.1188 - if (!hir)
1.1189 - return;
1.1190 -
1.1191 - switch (node->token()) {
1.1192 - case TOK_TILDE:
1.1193 - {
1.1194 - if (!hir->type()->isInt32() && !hir->type()->isEnum()) {
1.1195 - char name[255];
1.1196 - cc_.reportError(node->pos(), Message_InvalidUnaryType,
1.1197 - "~",
1.1198 - GetTypeName(hir->type(), name, sizeof(name)));
1.1199 - }
1.1200 - Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.1201 - hir_ = new (pool_) HUnary(node, hir->type(), TOK_TILDE, hir);
1.1202 - return;
1.1203 - }
1.1204 -
1.1205 - case TOK_MINUS:
1.1206 - {
1.1207 - if (hir->type()->isInt32() || hir->type()->isEnum()) {
1.1208 - Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.1209 - hir_ = new (pool_) HUnary(node, type, TOK_MINUS, hir);
1.1210 - return;
1.1211 - }
1.1212 - if (hir->type()->isFloat()) {
1.1213 - hir_ = new (pool_) HUnary(node, hir->type(), TOK_MINUS, hir);
1.1214 - return;
1.1215 - }
1.1216 -
1.1217 - char name[255];
1.1218 - cc_.reportError(node->pos(), Message_InvalidUnaryType,
1.1219 - "-",
1.1220 - GetTypeName(hir->type(), name, sizeof(name)));
1.1221 - break;
1.1222 - }
1.1223 -
1.1224 - default:
1.1225 - {
1.1226 - assert(node->token() == TOK_LABEL);
1.1227 -
1.1228 - TypeSymbol *sym = node->tag()->sym()->asType();
1.1229 - if (!sym) {
1.1230 - cc_.reportError(node->pos(), Message_IdentifierIsNotAType,
1.1231 - sym->name()->chars());
1.1232 - return;
1.1233 - }
1.1234 -
1.1235 - if (!IsValidUncheckedType(sym->effective())) {
1.1236 - char name[255];
1.1237 - cc_.reportError(node->pos(), Message_InvalidUncheckedCastTo,
1.1238 - GetTypeName(sym->type(), name, sizeof(name)));
1.1239 - return;
1.1240 - }
1.1241 - if (!IsValidUncheckedType(hir->type())) {
1.1242 - char name[255];
1.1243 - cc_.reportError(node->pos(), Message_InvalidUncheckedCastFrom,
1.1244 - GetTypeName(hir->type(), name, sizeof(name)));
1.1245 - return;
1.1246 - }
1.1247 -
1.1248 - hir_ = new (pool_) HUnary(node, sym->effective(), TOK_LABEL, hir);
1.1249 - break;
1.1250 - }
1.1251 - }
1.1252 -}
1.1253 -
1.1254 -void
1.1255 -SemanticAnalysis::import(HIR *hir, FieldExpression *node)
1.1256 -{
1.1257 - // Note that we don't care if the hir type is "importable", since we
1.1258 - // can only do anything if the important has a constant binding.
1.1259 - unsigned index = hir->toImport()->index();
1.1260 - Local<Importable> importable(zone_, unit_->module()->getImportAt(index));
1.1261 -
1.1262 - if (importable->isPackage()) {
1.1263 - // Look at what's already loaded and see if anything exists. We
1.1264 - // can't create stuff on-demand here since it's too late to add
1.1265 - // new translation units to the CompileContext.
1.1266 - Local<Package> package(zone_, Package::cast(importable));
1.1267 - Local<Importable> found(zone_, package->import(node->field()));
1.1268 - if (!found) {
1.1269 - cc_.reportError(node->pos(), Message_PackageDoesNotHaveMember, node->field()->chars());
1.1270 - return;
1.1271 - }
1.1272 -
1.1273 - // If we did find something, make sure it is in our import list.
1.1274 - // If we didn't explicitly import it, we have no right to use it.
1.1275 - for (index = 0; index < unit_->module()->imports(); index++) {
1.1276 - if (unit_->module()->getImportAt(index) == importable)
1.1277 - break;
1.1278 - }
1.1279 -
1.1280 - if (index == unit_->module()->imports()) {
1.1281 - cc_.reportError(node->pos(), Message_ImportWasNeverImported, node->field()->chars());
1.1282 - return;
1.1283 - }
1.1284 -
1.1285 - // Just create a new HImport.
1.1286 - hir_ = new (pool_) HImport(node, hir->type(), index);
1.1287 - } else {
1.1288 - // Modules can never have sub-modules or sub-packages.
1.1289 - unsigned index;
1.1290 - Local<Module> module(zone_, Module::cast(importable));
1.1291 - Local<StructMap> map(zone_, module->globals()->map());
1.1292 - Local<Descriptor> desc(zone_, map->type()->lookupField(node->field(), &index));
1.1293 - if (!desc) {
1.1294 - cc_.reportError(node->pos(), Message_FieldNotFound, node->field()->chars());
1.1295 - return;
1.1296 - }
1.1297 - hir_ = new (pool_) HField(node, hir, desc->type(), index);
1.1298 - }
1.1299 -}
1.1300 -
1.1301 -void
1.1302 -SemanticAnalysis::visitFieldExpression(FieldExpression *node)
1.1303 -{
1.1304 - HIR *hir = eval(node->left());
1.1305 - if (!hir)
1.1306 - return;
1.1307 -
1.1308 - if (hir->isImport()) {
1.1309 - import(hir, node);
1.1310 - return;
1.1311 - }
1.1312 -
1.1313 - char name[255];
1.1314 - cc_.reportError(node->pos(), Message_InvalidFieldExpression,
1.1315 - GetTypeName(hir->type(), name, sizeof(name)));
1.1316 -}
1.1317 -
1.1318 -static inline TokenKind
1.1319 -ToCompare(Expression *expr)
1.1320 -{
1.1321 - if (expr->isBinaryExpression()) {
1.1322 - BinaryExpression *b = expr->toBinaryExpression();
1.1323 - if (b->token() >= TOK_EQUALS && b->token() <= TOK_OR)
1.1324 - return b->token();
1.1325 - } else if (expr->isUnaryExpression()) {
1.1326 - UnaryExpression *u = expr->toUnaryExpression();
1.1327 - if (u->token() == TOK_NOT)
1.1328 - return TOK_NOT;
1.1329 - }
1.1330 - return TOK_EOF;
1.1331 -}
1.1332 -
1.1333 -void
1.1334 -SemanticAnalysis::visitForTest(Expression *expr,
1.1335 - Label *trueBranch,
1.1336 - Label *falseBranch,
1.1337 - Label *fallthrough)
1.1338 -{
1.1339 - Local<Type> boolType(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
1.1340 -
1.1341 - TokenKind token = ToCompare(expr);
1.1342 - if (token == TOK_EOF || token == TOK_NOT) {
1.1343 - HIR *hir;
1.1344 - if (token == TOK_EOF)
1.1345 - hir = eval(expr);
1.1346 - else
1.1347 - hir = eval(expr->toUnaryExpression()->expression());
1.1348 - if (!hir)
1.1349 - return;
1.1350 - if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
1.1351 - return;
1.1352 -
1.1353 - discharge(hir);
1.1354 -
1.1355 - bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
1.1356 - Opcode op = jumpOnTrue ? OP_JT : OP_JF;
1.1357 -
1.1358 - if (fallthrough == falseBranch)
1.1359 - __ j(op, trueBranch);
1.1360 - else
1.1361 - __ j(op, falseBranch);
1.1362 - return;
1.1363 - }
1.1364 -
1.1365 - BinaryExpression *bin = expr->toBinaryExpression();
1.1366 - if (token == TOK_AND || token == TOK_OR) {
1.1367 - Label next;
1.1368 - if (token == TOK_AND)
1.1369 - visitForTest(bin->left(), &next, falseBranch, &next);
1.1370 - else
1.1371 - visitForTest(bin->left(), trueBranch, &next, &next);
1.1372 - __ bind(&next);
1.1373 - visitForTest(bin->right(), trueBranch, falseBranch, fallthrough);
1.1374 - return;
1.1375 - }
1.1376 -
1.1377 - HIR *left = eval(bin->left());
1.1378 - HIR *right = eval(bin->right());
1.1379 - if (!left || !right)
1.1380 - return;
1.1381 -
1.1382 - HIR *hir = binary(bin, bin->token(), left, right);
1.1383 - if (!hir)
1.1384 - return;
1.1385 - if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
1.1386 - return;
1.1387 -
1.1388 - discharge(hir);
1.1389 - if (fallthrough == trueBranch)
1.1390 - __ j(OP_JF, falseBranch);
1.1391 - else
1.1392 - __ j(OP_JT, trueBranch);
1.1393 -}
1.1394 -
1.1395 -HLValue *
1.1396 -SemanticAnalysis::lvalue(Expression *expr)
1.1397 -{
1.1398 - HIR *hir = eval(expr);
1.1399 - if (!hir)
1.1400 - return NULL;
1.1401 -
1.1402 - if (!hir->isLValue()) {
1.1403 - cc_.reportError(expr->pos(), Message_ExpectedLValue);
1.1404 - return NULL;
1.1405 - }
1.1406 -
1.1407 - return static_cast<HLValue *>(hir);
1.1408 -}
1.1409 -
1.1410 -HIR *
1.1411 -SemanticAnalysis::eval(Expression *expr)
1.1412 -{
1.1413 - assert(!hir_);
1.1414 - expr->accept(this);
1.1415 -
1.1416 - HIR *hir = hir_;
1.1417 - hir_ = NULL;
1.1418 -
1.1419 - return hir;
1.1420 -}
1.1421 -
1.1422 -void
1.1423 -SemanticAnalysis::discharge(HIR *hir)
1.1424 -{
1.1425 - EmitHIR(zone_, emitter_, hir);
1.1426 -}
1.1427 +/* vim: set ts=4 sw=4 tw=99 et:
1.1428 + *
1.1429 + * Copyright (C) 2012 David Anderson
1.1430 + *
1.1431 + * This file is part of SourcePawn.
1.1432 + *
1.1433 + * SourcePawn is free software: you can redistribute it and/or modify it under
1.1434 + * the terms of the GNU General Public License as published by the Free
1.1435 + * Software Foundation, either version 3 of the License, or (at your option)
1.1436 + * any later version.
1.1437 + *
1.1438 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
1.1439 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.1440 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.1441 + *
1.1442 + * You should have received a copy of the GNU General Public License along with
1.1443 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
1.1444 + */
1.1445 +#include <assert.h>
1.1446 +#include "../Zone.h"
1.1447 +#include "../Strings.h"
1.1448 +#include "../NativeTable.h"
1.1449 +#include "../TypeManager.h"
1.1450 +#include "../Modules.h"
1.1451 +#include "../Code.h"
1.1452 +#include "SemanticAnalysis.h"
1.1453 +#include "../Heap-inl.h"
1.1454 +
1.1455 +using namespace ke;
1.1456 +
1.1457 +#define __ emitter_.
1.1458 +
1.1459 +typedef BytecodeEmitter::Label Label;
1.1460 +
1.1461 +class AutoEnterScope
1.1462 +{
1.1463 + public:
1.1464 + AutoEnterScope(Scope **prevp, Scope *scope)
1.1465 + : prevp_(prevp),
1.1466 + prev_(*prevp),
1.1467 + scope_(scope)
1.1468 + {
1.1469 + if (!scope_)
1.1470 + return;
1.1471 + prev_ = *prevp_;
1.1472 + *prevp_ = scope;
1.1473 + assert(prev_ == scope->enclosing());
1.1474 + }
1.1475 + ~AutoEnterScope()
1.1476 + {
1.1477 + if (scope_)
1.1478 + *prevp_ = prev_;
1.1479 + }
1.1480 + private:
1.1481 + Scope **prevp_;
1.1482 + Scope *prev_;
1.1483 + Scope *scope_;
1.1484 +};
1.1485 +
1.1486 +SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, TranslationUnit *unit)
1.1487 + : zone_(zone),
1.1488 + pool_(zone->pool()),
1.1489 + cc_(cc),
1.1490 + unit_(unit),
1.1491 + hir_(NULL),
1.1492 + loop_(NULL)
1.1493 +{
1.1494 +}
1.1495 +
1.1496 +SemanticAnalysis::SemanticAnalysis(SemanticAnalysis *parent, Handle<FunctionType> fun)
1.1497 + : zone_(parent->zone_),
1.1498 + pool_(parent->pool_),
1.1499 + cc_(parent->cc_),
1.1500 + unit_(parent->unit_),
1.1501 + hir_(NULL),
1.1502 + scope_(parent->scope_),
1.1503 + fun_(fun),
1.1504 + loop_(NULL),
1.1505 + control_(NULL)
1.1506 +{
1.1507 +
1.1508 +}
1.1509 +
1.1510 +void
1.1511 +SemanticAnalysis::analyze()
1.1512 +{
1.1513 + scope_ = unit_->globalScope();
1.1514 +
1.1515 + for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
1.1516 + Statement *stmt = unit_->tree()->statements()->at(i);
1.1517 + stmt->accept(this);
1.1518 + }
1.1519 +
1.1520 + Local<Code> code(zone_, __ finish());
1.1521 + if (!code)
1.1522 + return;
1.1523 + code->setModule(unit_->module());
1.1524 + unit_->module()->setCode(code);
1.1525 +
1.1526 +#ifndef NDEBUG
1.1527 +// Disassemble(code, stdout);
1.1528 +#endif
1.1529 +}
1.1530 +
1.1531 +void
1.1532 +SemanticAnalysis::visitFunctionStatement(FunctionStatement *stmt)
1.1533 +{
1.1534 + FunctionSymbol *sym = stmt->sym();
1.1535 + Local<FunctionType> type(zone_, sym->type());
1.1536 +
1.1537 + assert(scope_->kind() == Scope::GLOBAL);
1.1538 +
1.1539 + if (stmt->token() == TOK_NATIVE) {
1.1540 + // Define the native now.
1.1541 + size_t index;
1.1542 + if (!zone_->nativeTable()->add(stmt->name(), &index))
1.1543 + return;
1.1544 +
1.1545 + Local<Native> native(zone_, Native::New(zone_, type, index));
1.1546 + if (!native)
1.1547 + return;
1.1548 +
1.1549 + __ object(native);
1.1550 + __ setglobal(sym);
1.1551 + __ pop();
1.1552 + }
1.1553 +
1.1554 + // If the function is a forward or native, we don't have to do anything.
1.1555 + if (stmt->token() == TOK_NATIVE || stmt->token() == TOK_FORWARD)
1.1556 + return;
1.1557 +
1.1558 + SemanticAnalysis child(this, type);
1.1559 + Local<Function> funobj(zone_, child.compile(stmt));
1.1560 + if (!funobj)
1.1561 + return;
1.1562 +
1.1563 + __ object(funobj);
1.1564 + __ setglobal(sym);
1.1565 + if (stmt->token() == TOK_PUBLIC)
1.1566 + __ public_();
1.1567 + else
1.1568 + __ pop();
1.1569 +}
1.1570 +
1.1571 +Function *
1.1572 +SemanticAnalysis::compile(FunctionStatement *stmt)
1.1573 +{
1.1574 + __ setFirstLine(stmt->pos().line);
1.1575 +
1.1576 + AutoEnterScope argScope(&scope_, stmt->argScope());
1.1577 +
1.1578 + for (size_t i = 0; i < stmt->signature().parameters()->length(); i++) {
1.1579 + Parameter *param = stmt->signature().parameters()->at(i);
1.1580 + param->sym()->allocate(VariableSymbol::Arg, i);
1.1581 + }
1.1582 +
1.1583 + AutoEnterScope varScope(&scope_, stmt->varScope());
1.1584 + ControlStatus status = visitForControl(stmt->body());
1.1585 +
1.1586 + if (!fun_->returnType()->isVoid()) {
1.1587 + // If the function is not void, report if not all paths return a value.
1.1588 + // All other incorrect return cases have been caught already.
1.1589 + if (status.returns() == Returns_Sometimes) {
1.1590 + cc_.reportError(stmt->pos(), Message_NotAllPathsReturnValue);
1.1591 + return NULL;
1.1592 + }
1.1593 +
1.1594 + if (status.returns() == Returns_Never) {
1.1595 + cc_.reportError(stmt->pos(), Message_MissingReturnValue);
1.1596 + return NULL;
1.1597 + }
1.1598 + }
1.1599 +
1.1600 + Local<Code> code(zone_, __ finish());
1.1601 + if (!code)
1.1602 + return NULL;
1.1603 + code->setModule(unit_->module());
1.1604 +
1.1605 + Local<Function> fun(zone_, Function::New(zone_, code, fun_, stmt->name(), stmt->pos()));
1.1606 + if (!fun)
1.1607 + return NULL;
1.1608 +
1.1609 +#ifndef NDEBUG
1.1610 +// Disassemble(code, stdout);
1.1611 +#endif
1.1612 +
1.1613 + return fun;
1.1614 +}
1.1615 +
1.1616 +void
1.1617 +SemanticAnalysis::visitBlockStatement(BlockStatement *node)
1.1618 +{
1.1619 + AutoEnterScope scope(&scope_, node->scope());
1.1620 +
1.1621 + for (size_t i = 0; i < node->statements()->length(); i++) {
1.1622 + Statement *stmt = node->statements()->at(i);
1.1623 + __ note_position(stmt->pos());
1.1624 + stmt->accept(this);
1.1625 + assert(__ stackDepth() == 0);
1.1626 + }
1.1627 +}
1.1628 +
1.1629 +void
1.1630 +SemanticAnalysis::visitEnumStatement(EnumStatement *node)
1.1631 +{
1.1632 +}
1.1633 +
1.1634 +void
1.1635 +SemanticAnalysis::visitExpressionStatement(ExpressionStatement *node)
1.1636 +{
1.1637 + // While building HIR, we enter new pool and root scopes, since HIR
1.1638 + // creation is purely temporary.
1.1639 + PoolScope poolScope(zone_->pool());
1.1640 + RootScope rootScope(zone_);
1.1641 +
1.1642 + HIR *hir = eval(node->expression());
1.1643 + if (!hir)
1.1644 + return;
1.1645 +
1.1646 + discharge(hir);
1.1647 + if (!hir->type()->isVoid())
1.1648 + __ pop();
1.1649 +}
1.1650 +
1.1651 +void
1.1652 +SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
1.1653 +{
1.1654 + // If both sides terminate in a return, we consider this a return as well.
1.1655 + if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
1.1656 + terminate(Returns_Always);
1.1657 + return;
1.1658 + }
1.1659 +
1.1660 + ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
1.1661 + ? Returns_Never
1.1662 + : Returns_Sometimes;
1.1663 +
1.1664 + if (left.terminates() && right.terminates())
1.1665 + terminate(status);
1.1666 + else
1.1667 + returns(status);
1.1668 +}
1.1669 +
1.1670 +SemanticAnalysis::ControlStatus
1.1671 +SemanticAnalysis::visitForControl(Statement *statement)
1.1672 +{
1.1673 + ControlScope scope(&control_);
1.1674 + statement->accept(this);
1.1675 + return scope.status();
1.1676 +}
1.1677 +
1.1678 +void
1.1679 +SemanticAnalysis::visitIfStatement(IfStatement *node)
1.1680 +{
1.1681 + Label join;
1.1682 +
1.1683 + ControlStatus trueBranch;
1.1684 + ControlStatus falseBranch(false, Returns_Never);
1.1685 +
1.1686 + if (!node->ifFalse()) {
1.1687 + Label success;
1.1688 +
1.1689 + visitForTest(node->condition(), &success, &join, &success);
1.1690 + __ bind(&success);
1.1691 + trueBranch = visitForControl(node->ifTrue());
1.1692 + } else {
1.1693 + Label success, next;
1.1694 +
1.1695 + visitForTest(node->condition(), &success, &next, &success);
1.1696 + __ bind(&success);
1.1697 + trueBranch = visitForControl(node->ifTrue());
1.1698 + __ jump(&join);
1.1699 + __ bind(&next);
1.1700 + falseBranch = visitForControl(node->ifFalse());
1.1701 + }
1.1702 +
1.1703 + __ bind(&join);
1.1704 +
1.1705 + control_->merge(trueBranch, falseBranch);
1.1706 +}
1.1707 +
1.1708 +void
1.1709 +SemanticAnalysis::requireLifoStack()
1.1710 +{
1.1711 + if (!loop_)
1.1712 + return;
1.1713 +
1.1714 + loop_->setUsesLifoStack();
1.1715 +}
1.1716 +
1.1717 +SemanticAnalysis::ControlStatus
1.1718 +SemanticAnalysis::visitLoopBody(Statement *stmt)
1.1719 +{
1.1720 + // We always mark off a loop body, so on each edge, we can balance the
1.1721 + // LIFO stack. Right now, we don't have the ability to budget the LIFO
1.1722 + // stack ahead of time. If we turn out to never need the LIFO stack, we
1.1723 + // mark it as unnecessary. (The interpreter can't really make use of this,
1.1724 + // but the JIT can).
1.1725 + //
1.1726 + // Note that balancing the LIFO stack isn't even necessary, so this
1.1727 + // feature may be removed. All this mechanism does is mitigate the
1.1728 + // possibility that a long-running loop will overflow the LIFO region
1.1729 + // and therefore start requiring nursery allocations.
1.1730 + int pos = __ enterloop();
1.1731 + ControlStatus status = visitForControl(stmt);
1.1732 + __ leaveloop();
1.1733 +
1.1734 + if (loop_->usesLifoStack())
1.1735 + __ setLoopUsesLifoStack(pos);
1.1736 +
1.1737 + return status;
1.1738 +}
1.1739 +
1.1740 +void
1.1741 +SemanticAnalysis::visitForStatement(ForStatement *node)
1.1742 +{
1.1743 + AutoEnterScope scope(&scope_, node->scope());
1.1744 + PoolScope poolScope(zone_->pool());
1.1745 + RootScope rootScope(zone_);
1.1746 +
1.1747 + Label join, update;
1.1748 + LoopScope loop(scope_, &join, &update, &loop_);
1.1749 +
1.1750 + if (node->initialization())
1.1751 + node->initialization()->accept(this);
1.1752 +
1.1753 + Label header, test;
1.1754 + if (node->condition())
1.1755 + __ jump(&test);
1.1756 +
1.1757 + __ bind(&header);
1.1758 + ControlStatus status = visitLoopBody(node->body());
1.1759 +
1.1760 + __ bind(&update);
1.1761 + if (node->update())
1.1762 + node->update()->accept(this);
1.1763 +
1.1764 + if (node->condition()) {
1.1765 + __ bind(&test);
1.1766 + visitForTest(node->condition(), &header, &join, &join);
1.1767 + } else {
1.1768 + __ jump(&header);
1.1769 + }
1.1770 +
1.1771 + __ bind(&join);
1.1772 +
1.1773 + // If there was a condition, we treat this like a while loop. Otherwise,
1.1774 + // the join point is only reachable if the loop contains a break. The
1.1775 + // termination status doesn't tell us anything yet.
1.1776 + if (node->condition() || loop.breaks())
1.1777 + control_->merge(status, ControlStatus(false, Returns_Never));
1.1778 + else
1.1779 + control_->terminate(status.returns());
1.1780 +
1.1781 + assert(__ stackDepth() == 0);
1.1782 +}
1.1783 +
1.1784 +void
1.1785 +SemanticAnalysis::visitWhileStatement(WhileStatement *node)
1.1786 +{
1.1787 + PoolScope poolScope(zone_->pool());
1.1788 + RootScope rootScope(zone_);
1.1789 +
1.1790 + Label header, join;
1.1791 +
1.1792 + __ bind(&header);
1.1793 +
1.1794 + ControlStatus status;
1.1795 +
1.1796 + LoopScope loop(scope_, &join, &header, &loop_);
1.1797 + if (node->token() == TOK_WHILE) {
1.1798 + Label body;
1.1799 + visitForTest(node->condition(), &body, &join, &body);
1.1800 + status = visitLoopBody(node->body());
1.1801 + __ jump(&header);
1.1802 + } else {
1.1803 + status = visitLoopBody(node->body());
1.1804 + visitForTest(node->condition(), &header, &join, &join);
1.1805 + }
1.1806 +
1.1807 + __ bind(&join);
1.1808 +
1.1809 + // Detect loops that will always have a fork in the contro-flow graph.
1.1810 + // This will be a |while| loop, or a |do-while| loop whose body does
1.1811 + // not terminate. For now, we treat these as an |if| regardless of the
1.1812 + // direction the branch can take. That means the control-flow is always
1.1813 + // conditional.
1.1814 + if (node->token() == TOK_WHILE || status.terminates() || loop.breaks()) {
1.1815 + control_->merge(status, ControlStatus(false, Returns_Never));
1.1816 + } else {
1.1817 + // At this point, we've got a do-while loop with a |return| or
1.1818 + // |continue|, meaning that the rest of the block is unreachable.
1.1819 + control_->terminate(status.returns());
1.1820 + }
1.1821 +
1.1822 + assert(__ stackDepth() == 0);
1.1823 +}
1.1824 +
1.1825 +static inline Heap::Tenure
1.1826 +InferTenure(Symbol *sym)
1.1827 +{
1.1828 + if (sym->scope()->kind() == Scope::GLOBAL)
1.1829 + return Heap::Tenure_Old;
1.1830 +
1.1831 + // SP2's array semantics allow any array kind to escape, so we must use
1.1832 + // the normal heap. (Hopefully escape analysis can ease this pain later).
1.1833 + if (sym->type()->isArray())
1.1834 + return Heap::Tenure_Default;
1.1835 +
1.1836 + return Heap::Tenure_Default;
1.1837 +}
1.1838 +
1.1839 +void
1.1840 +SemanticAnalysis::visitVariableDeclaration(VariableDeclaration *node)
1.1841 +{
1.1842 + PoolScope poolScope(zone_->pool());
1.1843 + RootScope rootScope(zone_);
1.1844 +
1.1845 + Local<Type> type(zone_, node->sym()->type());
1.1846 +
1.1847 + if (node->sym()->type()->isVoid()) {
1.1848 + cc_.reportError(node->type()->pos(), Message_CannotDeclareVoid);
1.1849 + return;
1.1850 + }
1.1851 +
1.1852 + if (node->initialization()) {
1.1853 + HIR *hir = NULL;
1.1854 +
1.1855 + if ((hir = eval(node->initialization())) == NULL)
1.1856 + return;
1.1857 + if ((hir = coerce(hir, type, Coerce_Decl)) == NULL)
1.1858 + return;
1.1859 +
1.1860 + discharge(hir);
1.1861 + } else {
1.1862 + if (type->isInt32() || type->isEnum() ||
1.1863 + type->isChar() || type->isBool())
1.1864 + {
1.1865 + __ int_(0);
1.1866 + } else if (type->isFloat()) {
1.1867 + __ float_(0);
1.1868 + } else if (type->isArray()) {
1.1869 + Local<ArrayType> atype(zone_, ArrayType::cast(type));
1.1870 + Local<ArrayMap> map(zone_, atype->newMap());
1.1871 + if (!map)
1.1872 + return;
1.1873 +
1.1874 + if (atype->isFixedLength()) {
1.1875 + __ newarray(OP_NEWFIXED, map, InferTenure(node->sym()));
1.1876 + } else if (node->dims()->at(0)) {
1.1877 + // This may not be true if we allow typedefing, so :TODO:
1.1878 + // figure out proper semantics.
1.1879 + assert(node->dims()->length() == atype->levels());
1.1880 +
1.1881 + Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.1882 + for (size_t i = 0; i < node->dims()->length(); i++) {
1.1883 + Expression *expr = node->dims()->at(i);
1.1884 + if (expr) {
1.1885 + HIR *hir = eval(expr);
1.1886 + if (!hir || ((hir = coerce(hir, i32, Coerce_Arg)) == NULL))
1.1887 + return;
1.1888 + discharge(hir);
1.1889 + } else {
1.1890 + __ int_(0);
1.1891 + }
1.1892 + }
1.1893 + __ newarray(OP_NEWSIZED, map, InferTenure(node->sym()));
1.1894 + } else {
1.1895 + __ newarray(OP_NEWEMPTY, map, InferTenure(node->sym()));
1.1896 + }
1.1897 + } else {
1.1898 + assert(false);
1.1899 + }
1.1900 + }
1.1901 +
1.1902 + if (node->sym()->scope()->kind() != Scope::GLOBAL) {
1.1903 + if (!__ allocate(node->sym()))
1.1904 + return;
1.1905 + }
1.1906 +
1.1907 + set(node->sym());
1.1908 + __ pop();
1.1909 +}
1.1910 +
1.1911 +void
1.1912 +SemanticAnalysis::visitReturnStatement(ReturnStatement *node)
1.1913 +{
1.1914 + control_->returns(Returns_Always);
1.1915 +
1.1916 + if (!node->expression()) {
1.1917 + if (!fun_->returnType()->isVoid()) {
1.1918 + cc_.reportError(node->pos(), Message_MissingReturnValue);
1.1919 + return;
1.1920 + }
1.1921 +
1.1922 + __ returnvoid();
1.1923 + return;
1.1924 + }
1.1925 +
1.1926 + if (fun_->returnType()->isVoid()) {
1.1927 + cc_.reportError(node->pos(), Message_UsedVoidReturn);
1.1928 + return;
1.1929 + }
1.1930 +
1.1931 + PoolScope poolScope(zone_->pool());
1.1932 + RootScope rootScope(zone_);
1.1933 +
1.1934 + HIR *hir = eval(node->expression());
1.1935 + if (!hir)
1.1936 + return;
1.1937 +
1.1938 + Local<Type> returnType(zone_, fun_->returnType());
1.1939 + if ((hir = coerce(hir, returnType, Coerce_Return)) == NULL)
1.1940 + return;
1.1941 +
1.1942 + discharge(hir);
1.1943 +
1.1944 + if (hir->type()->isVoid())
1.1945 + __ returnvoid();
1.1946 + else
1.1947 + __ return_();
1.1948 +}
1.1949 +
1.1950 +void
1.1951 +SemanticAnalysis::visitBinaryExpression(BinaryExpression *node)
1.1952 +{
1.1953 + HIR *left = eval(node->left());
1.1954 + HIR *right = eval(node->right());
1.1955 + if (!left || !right)
1.1956 + return;
1.1957 +
1.1958 + hir_ = binary(node, node->token(), left, right);
1.1959 +}
1.1960 +
1.1961 +bool
1.1962 +SemanticAnalysis::checkArgumentCount(Handle<FunctionType> type, unsigned actual)
1.1963 +{
1.1964 + if (type->parameters()->length() == actual)
1.1965 + return true;
1.1966 +
1.1967 + if (actual > type->parameters()->length()) {
1.1968 + if (!type->isNative() || !type->isNativeVariadic())
1.1969 + return false;
1.1970 + return true;
1.1971 + }
1.1972 +
1.1973 + if (!type->defaults())
1.1974 + return false;
1.1975 +
1.1976 + // Missing arguments. See if there's a default argument for each missing
1.1977 + // actual.
1.1978 + for (unsigned i = actual; i < type->parameters()->length(); i++) {
1.1979 + if (!type->defaults()->at(i))
1.1980 + return false;
1.1981 + }
1.1982 +
1.1983 + return true;
1.1984 +}
1.1985 +
1.1986 +static unsigned
1.1987 +BindImplicitName(Module *from, ImplicitSymbol *sym)
1.1988 +{
1.1989 + if (sym->bound())
1.1990 + return sym->fieldIndex();
1.1991 +
1.1992 + Module *module = Module::cast(from->getImportAt(sym->index()));
1.1993 + StructMap *map = module->globals()->map();
1.1994 +
1.1995 + unsigned fieldIndex;
1.1996 + Descriptor *desc = map->type()->lookupField(sym->name(), &fieldIndex);
1.1997 + assert(desc && desc->type() == sym->type());
1.1998 +
1.1999 + sym->bind(fieldIndex);
1.2000 + return fieldIndex;
1.2001 +}
1.2002 +
1.2003 +void
1.2004 +SemanticAnalysis::visitNameProxy(NameProxy *proxy)
1.2005 +{
1.2006 + Symbol *sym = proxy->sym();
1.2007 +
1.2008 + switch (sym->kind()) {
1.2009 + case Symbol::kImport:
1.2010 + {
1.2011 + ImportSymbol *import = sym->toImport();
1.2012 + hir_ = new (pool_) HImport(proxy, sym->type(), import->index());
1.2013 + break;
1.2014 + }
1.2015 +
1.2016 + case Symbol::kImplicit:
1.2017 + {
1.2018 + ImplicitSymbol *import = sym->toImplicit();
1.2019 + unsigned fieldIndex = BindImplicitName(unit_->module(), import);
1.2020 +
1.2021 + hir_ = new (pool_) HImport(proxy, zone_->types()->getImportable(), import->index());
1.2022 + hir_ = new (pool_) HField(proxy, hir_, sym->type(), fieldIndex);
1.2023 + break;
1.2024 + }
1.2025 +
1.2026 + case Symbol::kConstant:
1.2027 + {
1.2028 + ConstantSymbol *val = sym->toConstant();
1.2029 + hir_ = new (pool_) HInteger(proxy, sym->type(), val->value().toInt());
1.2030 + break;
1.2031 + }
1.2032 +
1.2033 + // This is kind of screwy. Symbol::kFunction is like a constant we can't
1.2034 + // evaluate yet. Maybe we should extract the GLOBAL case and say that
1.2035 + // kFunction is only used for global functions (and use const vars for
1.2036 + // local functions).
1.2037 + case Symbol::kFunction:
1.2038 + case Symbol::kVariable:
1.2039 + {
1.2040 + Scope *in = sym->scope();
1.2041 + switch (in->kind()) {
1.2042 + case Scope::GLOBAL:
1.2043 + hir_ = new (pool_) HGlobal(proxy, sym);
1.2044 + break;
1.2045 +
1.2046 + case Scope::FUNCTION:
1.2047 + {
1.2048 + VariableSymbol *var = sym->toVariable();
1.2049 + assert(var->storage() == VariableSymbol::Arg);
1.2050 + hir_ = new (pool_) HLocal(proxy, var);
1.2051 + break;
1.2052 + }
1.2053 +
1.2054 + default:
1.2055 + {
1.2056 + VariableSymbol *var = sym->toVariable();
1.2057 + assert(in->kind() == Scope::BLOCK);
1.2058 + assert(var->storage() == VariableSymbol::Local);
1.2059 + hir_ = new (pool_) HLocal(proxy, var);
1.2060 + break;
1.2061 + }
1.2062 + }
1.2063 + break;
1.2064 + }
1.2065 +
1.2066 + default:
1.2067 + // :TODO:
1.2068 + assert(false);
1.2069 + }
1.2070 +}
1.2071 +
1.2072 +void
1.2073 +SemanticAnalysis::visitBooleanLiteral(BooleanLiteral *node)
1.2074 +{
1.2075 + Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
1.2076 + hir_ = new (pool_) HBoolean(node, type, node->token() == TOK_TRUE);
1.2077 +}
1.2078 +
1.2079 +void
1.2080 +SemanticAnalysis::visitIntegerLiteral(IntegerLiteral *lit)
1.2081 +{
1.2082 + Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.2083 + hir_ = new (pool_) HInteger(lit, type, lit->value());
1.2084 +}
1.2085 +
1.2086 +void
1.2087 +SemanticAnalysis::visitFloatLiteral(FloatLiteral *node)
1.2088 +{
1.2089 + Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
1.2090 + hir_ = new (pool_) HFloat(node, type, (float)node->value());
1.2091 +}
1.2092 +
1.2093 +void
1.2094 +SemanticAnalysis::visitStringLiteral(StringLiteral *node)
1.2095 +{
1.2096 + Type *type = zone_->types()->getString();
1.2097 + hir_ = new (pool_) HString(node, type, node->string());
1.2098 +}
1.2099 +
1.2100 +void
1.2101 +SemanticAnalysis::visitCallExpression(CallExpression *node)
1.2102 +{
1.2103 + HIR *callee = eval(node->callee());
1.2104 + if (!callee)
1.2105 + return;
1.2106 +
1.2107 + if (!callee->type()->isFunction()) {
1.2108 + cc_.reportError(node->pos(), Message_CalleeNotFunction);
1.2109 + return;
1.2110 + }
1.2111 +
1.2112 + Local<FunctionType> fun(zone_, FunctionType::cast(callee->type()));
1.2113 +
1.2114 + if (!checkArgumentCount(fun, node->arguments()->length())) {
1.2115 + cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
1.2116 + return;
1.2117 + }
1.2118 +
1.2119 + if (fun->isForward()) {
1.2120 + cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
1.2121 + return;
1.2122 + }
1.2123 +
1.2124 + HIRList *args = new (pool_) HIRList;
1.2125 + for (unsigned i = 0; i < node->arguments()->length(); i++) {
1.2126 + Expression *expression = node->arguments()->at(i);
1.2127 + HIR *arg = eval(expression);
1.2128 + if (!arg)
1.2129 + return;
1.2130 +
1.2131 + Handle<Type> given = arg->type();
1.2132 +
1.2133 + bool mustComputeReference;
1.2134 + if (i >= fun->parameters()->length()) {
1.2135 + // Special handling for natives. Arguments past the formal must
1.2136 + // always have references computed. However, arrays are already
1.2137 + // references for natives.
1.2138 + assert(fun->isNative() && fun->isNativeVariadic());
1.2139 + mustComputeReference = !given->isReference() &&
1.2140 + !given->isArray();
1.2141 + } else {
1.2142 + Local<Type> actual(zone_, fun->parameterAt(i));
1.2143 +
1.2144 + if (expression->isIndexExpression() && arg->isIndex()) {
1.2145 + // If the expression is the form x[y], and this produced a
1.2146 + // normal array indexing operation, then we apply some
1.2147 + // special rules.
1.2148 +
1.2149 + if (actual->isReference()) {
1.2150 + // Disabled, since this doesn't have easily definable or
1.2151 + // sensible semantics with SP2 arrays, but we don't want
1.2152 + // to silently break SP1 semantics.
1.2153 + cc_.reportError(expression->pos(), Message_CannotComputeIndexRef);
1.2154 + return;
1.2155 + }
1.2156 +
1.2157 + // As a special rule to account for SP1 semantics, we allow x[y]
1.2158 + // to automatically compute a sliced, read-only array view if
1.2159 + // the desired type is an array of one more dimension than x[y]
1.2160 + // would return.
1.2161 + //
1.2162 + // As an additional restriction, this is only allowed for
1.2163 + // one-level char arrays, to minimize potential issues until
1.2164 + // we determine whether more compatibility is needed.
1.2165 + //
1.2166 + // Internally, for sanity, the dependent array operation does
1.2167 + // not necessarily create a dependent array. For extensible
1.2168 + // arrays, we instead create a duplicate arrary of just the
1.2169 + // sliced portion, rather than deal with the complexity of the
1.2170 + // source array being resized.
1.2171 + //
1.2172 + // Note that we don't really know whether a dependent array
1.2173 + // will be dependent at compile-time, so the dependent type's
1.2174 + // just inherits from the source.
1.2175 + if (actual->isArray()) {
1.2176 + HIndex *index = arg->toIndex();
1.2177 + Local<ArrayType> basetype(zone_, ArrayType::cast(index->base()->type()));
1.2178 + Local<ArrayType> atype(zone_, ArrayType::cast(actual));
1.2179 +
1.2180 + if (atype->isCharArray() && basetype->isCharArray()) {
1.2181 + // There is no possible way this will type check, so
1.2182 + // it's safe to just try something completely
1.2183 + // different.
1.2184 + Local<Type> slicetype(zone_);
1.2185 + if (basetype->isFixedLength()) {
1.2186 + // If the base type is fixed length, we need to
1.2187 + // compute a new dynamic array type based on the
1.2188 + // fixed array's contents and qualifiers.
1.2189 + Local<Type> contained(zone_, basetype->contained());
1.2190 + slicetype = zone_->types()->newArray(contained, ArrayType::DYNAMIC_ARRAY_SIZE);
1.2191 + if (!slicetype)
1.2192 + return;
1.2193 + slicetype = zone_->types()->qualify(slicetype, basetype->quals());
1.2194 + if (!slicetype)
1.2195 + return;
1.2196 + } else {
1.2197 + slicetype = basetype;
1.2198 + }
1.2199 + arg = new (pool_) HNewDependentArray(expression, slicetype, index->base(), index->index());
1.2200 + given = arg->type();
1.2201 + }
1.2202 + }
1.2203 + }
1.2204 +
1.2205 + if (actual->isReference()) {
1.2206 + // If the actual is a reference, the coercion rules are much
1.2207 + // stricter; the contained types must be identical.
1.2208 + // :TODO: make this not an assert
1.2209 + assert(ReferenceType::cast(actual)->contained() == arg->type());
1.2210 + } else {
1.2211 + // When we start overloading, coercion will have to happen later.
1.2212 + arg = coerce(arg, actual, Coerce_Arg);
1.2213 + if (!arg)
1.2214 + return;
1.2215 + }
1.2216 +
1.2217 + mustComputeReference = actual->isReference() && !given->isReference();
1.2218 + }
1.2219 +
1.2220 + if (mustComputeReference) {
1.2221 + // Refs always use the LIFO stack if they can.
1.2222 + arg = new (pool_) HToRef(arg->node(), arg->type(), arg);
1.2223 + requireLifoStack();
1.2224 + }
1.2225 +
1.2226 + if (!args->append(arg))
1.2227 + return;
1.2228 + }
1.2229 +
1.2230 + hir_ = new (pool_) HCall(node, fun->returnType(), callee, args);
1.2231 +}
1.2232 +
1.2233 +void
1.2234 +SemanticAnalysis::visitAssignment(Assignment *node)
1.2235 +{
1.2236 + HLValue *lval = lvalue(node->lvalue());
1.2237 + if (!lval)
1.2238 + return;
1.2239 +
1.2240 + if (lval->type()->quals() & TypeQual_Const) {
1.2241 + cc_.reportError(node->pos(), Message_CannotModifyConst);
1.2242 + return;
1.2243 + }
1.2244 +
1.2245 + HIR *hir = eval(node->expression());
1.2246 + if (!hir)
1.2247 + return;
1.2248 + if ((hir = coerce(hir, lval->type(), Coerce_Assign)) == NULL)
1.2249 + return;
1.2250 +
1.2251 + hir_ = new (pool_) HStore(node, node->token(), lval, hir);
1.2252 +}
1.2253 +
1.2254 +void
1.2255 +SemanticAnalysis::visitBreakStatement(BreakStatement *node)
1.2256 +{
1.2257 + if (!loop_) {
1.2258 + cc_.reportError(node->pos(), Message_BreakOutsideLoop);
1.2259 + return;
1.2260 + }
1.2261 +
1.2262 + loop_->setBreaks();
1.2263 + __ j(OP_BREAK, loop_->break_());
1.2264 +}
1.2265 +
1.2266 +void
1.2267 +SemanticAnalysis::visitContinueStatement(ContinueStatement *node)
1.2268 +{
1.2269 + if (!loop_) {
1.2270 + cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
1.2271 + return;
1.2272 + }
1.2273 +
1.2274 + __ j(OP_CONTINUE, loop_->continue_());
1.2275 +}
1.2276 +
1.2277 +void
1.2278 +SemanticAnalysis::visitIndexExpression(IndexExpression *node)
1.2279 +{
1.2280 + HIR *left = eval(node->left());
1.2281 + if (!left)
1.2282 + return;
1.2283 +
1.2284 + HIR *right = eval(node->right());
1.2285 + if (!right)
1.2286 + return;
1.2287 +
1.2288 + // Hrm... yes, for now, let's coerce here.
1.2289 + Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.2290 + if ((right = coerce(right, i32, Coerce_Arg)) == NULL)
1.2291 + return;
1.2292 +
1.2293 + // Do not coerce here, there's no reason to yet.
1.2294 + if (!left->type()->isArray()) {
1.2295 + cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
1.2296 + return;
1.2297 + }
1.2298 +
1.2299 + hir_ = new (pool_) HIndex(node,
1.2300 + ArrayType::cast(left->type())->contained(),
1.2301 + left,
1.2302 + right);
1.2303 +}
1.2304 +
1.2305 +void
1.2306 +SemanticAnalysis::visitIncDecExpression(IncDecExpression *node)
1.2307 +{
1.2308 + HLValue *lval = lvalue(node->expression());
1.2309 + if (!lval)
1.2310 + return;
1.2311 +
1.2312 + if (!lval->type()->isInt32() && !lval->type()->isFloat()) {
1.2313 + assert(false);
1.2314 + return;
1.2315 + }
1.2316 +
1.2317 + HIR *rval;
1.2318 + if (lval->type()->isInt32())
1.2319 + rval = new (pool_) HInteger(node, lval->type(), 1);
1.2320 + else
1.2321 + rval = new (pool_) HFloat(node, lval->type(), 1.0);
1.2322 +
1.2323 + if (node->postfix())
1.2324 + hir_ = new (pool_) HPostIncDec(node, node->token(), lval, rval);
1.2325 + else
1.2326 + hir_ = new (pool_) HStore(node, node->token(), lval, rval);
1.2327 +}
1.2328 +
1.2329 +Type *
1.2330 +SemanticAnalysis::coercionType(TokenKind token, HIR *left, HIR *right)
1.2331 +{
1.2332 + Local<Type> l(zone_, left->type());
1.2333 + Local<Type> r(zone_, right->type());
1.2334 +
1.2335 + if (l->isPod())
1.2336 + l = l->unqualified();
1.2337 + if (r->isPod())
1.2338 + r = r->unqualified();
1.2339 +
1.2340 + if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
1.2341 + (token >= TOK_EQUALS && token <= TOK_GE))
1.2342 + {
1.2343 + // We allow: [float|int32] + [float|int32]
1.2344 + if (l->isFloat() && r->isInt32())
1.2345 + return l;
1.2346 + if (l->isInt32() && r->isFloat())
1.2347 + return r;
1.2348 + if (l->isInt32() && r->isInt32())
1.2349 + return l;
1.2350 +
1.2351 + if (l->isChar() && r->isInt32())
1.2352 + return r;
1.2353 + if (l->isInt32() && r->isChar())
1.2354 + return l;
1.2355 + }
1.2356 +
1.2357 + // :TODO: remove
1.2358 + assert(*l == *r);
1.2359 +
1.2360 + return left->type();
1.2361 +}
1.2362 +
1.2363 +HIR *
1.2364 +SemanticAnalysis::typeCheckArray(const SourcePosition &pos,
1.2365 + HIR *from,
1.2366 + Handle<ArrayType> argActual,
1.2367 + CoercionKind kind)
1.2368 +{
1.2369 + Local<Type> argGiven(zone_, from->type());
1.2370 +
1.2371 + // Special case: if we receive a string literal, and this is a char array,
1.2372 + // we allow a coercion.
1.2373 + if (from->isString() &&
1.2374 + argGiven->isString() &&
1.2375 + argActual->isArray() &&
1.2376 + ArrayType::cast(argActual)->isCharArray())
1.2377 + {
1.2378 + HString *hir = from->toString();
1.2379 + Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
1.2380 +
1.2381 + if (actual->isFixedLength()) {
1.2382 + if (hir->string()->length() + 1 > actual->fixedLength()) {
1.2383 + cc_.reportError(pos, Message_ArrayAssignmentTooBig);
1.2384 + return NULL;
1.2385 + }
1.2386 + }
1.2387 +
1.2388 + // Transform the string literal into an array literal. We give it the
1.2389 + // type of the left-hand side. The constness of the destination type
1.2390 + // will determine whether HArray duplicates it or not.
1.2391 + Local<ArrayMap> map(zone_, actual->newMap());
1.2392 + if (!map)
1.2393 + return NULL;
1.2394 +
1.2395 + Local<Array> array(zone_);
1.2396 + array = Array::NewString(zone_,
1.2397 + map,
1.2398 + hir->string()->chars(),
1.2399 + hir->string()->length(),
1.2400 + Heap::Tenure_Old);
1.2401 + if (!array)
1.2402 + return NULL;
1.2403 +
1.2404 + // Since we're creating a canonical copy of the char array, we have to
1.2405 + // be careful that it doesn't get mutated. There are two cases where
1.2406 + // we know it can't be mutated, and therefore don't need to specify
1.2407 + // that it be cloned after pushing it onto the stack.
1.2408 + //
1.2409 + // (1) The array type is const.
1.2410 + // (2) The array type is fixed-length, and the coercion is for
1.2411 + // assignment, meaning it will be immediately copied.
1.2412 + //
1.2413 + // We treat declaration separately from assignment, since for
1.2414 + // declaration we can just immediately use the cloned version.
1.2415 + bool shouldDuplicate = true;
1.2416 + if ((actual->quals() & TypeQual_Const) ||
1.2417 + (actual->isFixedLength() && kind == Coerce_Assign))
1.2418 + {
1.2419 + shouldDuplicate = false;
1.2420 + }
1.2421 +
1.2422 + return new (pool_) HArray(hir->node(), actual, array, shouldDuplicate);
1.2423 + }
1.2424 +
1.2425 + if (!argGiven->isArray()) {
1.2426 + cc_.reportError(pos, Message_ExpectedArray);
1.2427 + return NULL;
1.2428 + }
1.2429 +
1.2430 + Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
1.2431 + Local<ArrayType> given(zone_, ArrayType::cast(argGiven));
1.2432 +
1.2433 + if (actual->levels() != given->levels()) {
1.2434 + cc_.reportError(pos, Message_ArrayDimensionsMismatch);
1.2435 + return NULL;
1.2436 + }
1.2437 +
1.2438 + unsigned level = 1;
1.2439 + while (true) {
1.2440 + if (actual->isFixedLength()) {
1.2441 + if (!given->isFixedLength()) {
1.2442 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.2443 + return NULL;
1.2444 + }
1.2445 +
1.2446 + if (actual->isCharArray()) {
1.2447 + // String assignment can have a truncated |given|.
1.2448 + if (given->fixedLength() > actual->fixedLength()) {
1.2449 + cc_.reportError(pos, Message_ArrayAssignmentTooBig);
1.2450 + return NULL;
1.2451 + }
1.2452 + } else {
1.2453 + if (given->fixedLength() != actual->fixedLength()) {
1.2454 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.2455 + return NULL;
1.2456 + }
1.2457 + }
1.2458 + } else if (given->isFixedLength()) {
1.2459 + // We do not allow assignments in the form:
1.2460 + // [][] = [][Y]
1.2461 + //
1.2462 + // Otherwise, the following code could break the size guarantees
1.2463 + // of the right-hand side:
1.2464 + //
1.2465 + // new x[][5];
1.2466 + // new y[][];
1.2467 + // new z[3];
1.2468 + //
1.2469 + //
1.2470 + // y = x;
1.2471 + // y[0] = z;
1.2472 + //
1.2473 + // Now |x[0]| contains a 3-length array.
1.2474 + if (level > 1) {
1.2475 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.2476 + return NULL;
1.2477 + }
1.2478 + }
1.2479 +
1.2480 + if (!given->contained()->isArray() || !actual->contained()->isArray())
1.2481 + break;
1.2482 +
1.2483 + given = ArrayType::cast(given->contained());
1.2484 + actual = ArrayType::cast(actual->contained());
1.2485 + }
1.2486 +
1.2487 + bool givenConst = !!(given->contained()->quals() & TypeQual_Const);
1.2488 + bool actualConst = !!(actual->contained()->quals() & TypeQual_Const);
1.2489 +
1.2490 + // These arrays must contain the same innermost type.
1.2491 + if (given->contained()->unqualified() != actual->contained()->unqualified() ||
1.2492 + (givenConst && !actualConst))
1.2493 + {
1.2494 + char aname[255];
1.2495 + char gname[255];
1.2496 + cc_.reportError(pos, Message_TypeMismatch,
1.2497 + GetTypeName(argActual, aname, sizeof(aname)),
1.2498 + GetTypeName(argGiven, gname, sizeof(gname)));
1.2499 + return NULL;
1.2500 + }
1.2501 +
1.2502 + return from;
1.2503 +}
1.2504 +
1.2505 +HIR *
1.2506 +SemanticAnalysis::typeFailure(const SourcePosition &pos, Handle<Type> from, Handle<Type> to)
1.2507 +{
1.2508 + char fname[255];
1.2509 + char tname[255];
1.2510 + cc_.reportError(pos, Message_InvalidCoercion,
1.2511 + GetTypeName(from, fname, sizeof(fname)),
1.2512 + GetTypeName(to, tname, sizeof(tname)));
1.2513 + return NULL;
1.2514 +}
1.2515 +
1.2516 +HIR *
1.2517 +SemanticAnalysis::coerce(HIR *hir, Handle<Type> to, CoercionKind kind)
1.2518 +{
1.2519 + Local<Type> from(zone_, hir->type());
1.2520 +
1.2521 + // If the source is *ever* an importable, we just fail.
1.2522 + if (from->isImportable())
1.2523 + return typeFailure(hir->node()->pos(), from, to);
1.2524 +
1.2525 + if (from->isInt32() && to->isFloat())
1.2526 + return new (pool_) HConvert(hir->node(), to, OP_CVT_I2F, hir);
1.2527 + if (from->isInt32() && to->isBool())
1.2528 + return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir);
1.2529 +
1.2530 + if (to->isEnum() && from->unqualified() != to->unqualified())
1.2531 + return typeFailure(hir->node()->pos(), from, to);
1.2532 +
1.2533 + if (to->isArray()) {
1.2534 + Local<ArrayType> atype(zone_, ArrayType::cast(to));
1.2535 + return typeCheckArray(hir->node()->pos(), hir, atype, kind);
1.2536 + }
1.2537 +
1.2538 + return hir;
1.2539 +}
1.2540 +
1.2541 +void
1.2542 +SemanticAnalysis::set(VariableSymbol *sym)
1.2543 +{
1.2544 + if (sym->scope()->kind() == Scope::GLOBAL) {
1.2545 + __ setglobal(sym);
1.2546 + } else {
1.2547 + assert(sym->storage() == VariableSymbol::Local);
1.2548 + __ setlocal(sym);
1.2549 + }
1.2550 +}
1.2551 +
1.2552 +HIR *
1.2553 +SemanticAnalysis::binary(AstNode *node, TokenKind token, HIR *left, HIR *right)
1.2554 +{
1.2555 + Local<Type> coercion(zone_, coercionType(token, left, right));
1.2556 + if (!coercion)
1.2557 + return NULL;
1.2558 + if ((left = coerce(left, coercion, Coerce_Arg)) == NULL)
1.2559 + return NULL;
1.2560 + if ((right = coerce(right, coercion, Coerce_Arg)) == NULL)
1.2561 + return NULL;
1.2562 +
1.2563 + switch (token) {
1.2564 + case TOK_PLUS:
1.2565 + case TOK_MINUS:
1.2566 + case TOK_STAR:
1.2567 + case TOK_SLASH:
1.2568 + case TOK_PERCENT:
1.2569 + case TOK_AMPERSAND:
1.2570 + case TOK_BITOR:
1.2571 + case TOK_BITXOR:
1.2572 + case TOK_SHR:
1.2573 + case TOK_USHR:
1.2574 + case TOK_SHL:
1.2575 + return new (pool_) HBinary(node, left->type(), token, left, right);
1.2576 +
1.2577 + case TOK_EQUALS:
1.2578 + case TOK_NOTEQUALS:
1.2579 + case TOK_LT:
1.2580 + case TOK_LE:
1.2581 + case TOK_GT:
1.2582 + case TOK_GE:
1.2583 + case TOK_AND:
1.2584 + case TOK_OR:
1.2585 + {
1.2586 + Local<Type> result(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
1.2587 + return new (pool_) HBinary(node, result, token, left, right);
1.2588 + }
1.2589 +
1.2590 + default:
1.2591 + assert(false);
1.2592 + return NULL;
1.2593 + }
1.2594 +}
1.2595 +
1.2596 +static inline bool
1.2597 +IsValidUncheckedType(Type *type)
1.2598 +{
1.2599 + return type->isEnum() ||
1.2600 + type->isFloat() ||
1.2601 + type->isInt32() ||
1.2602 + type->isChar() ||
1.2603 + type->isUnchecked() ||
1.2604 + type->isBool();
1.2605 +}
1.2606 +
1.2607 +void
1.2608 +SemanticAnalysis::visitUnaryExpression(UnaryExpression *node)
1.2609 +{
1.2610 + HIR *hir = eval(node->expression());
1.2611 + if (!hir)
1.2612 + return;
1.2613 +
1.2614 + switch (node->token()) {
1.2615 + case TOK_TILDE:
1.2616 + {
1.2617 + if (!hir->type()->isInt32() && !hir->type()->isEnum()) {
1.2618 + char name[255];
1.2619 + cc_.reportError(node->pos(), Message_InvalidUnaryType,
1.2620 + "~",
1.2621 + GetTypeName(hir->type(), name, sizeof(name)));
1.2622 + }
1.2623 + Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.2624 + hir_ = new (pool_) HUnary(node, hir->type(), TOK_TILDE, hir);
1.2625 + return;
1.2626 + }
1.2627 +
1.2628 + case TOK_MINUS:
1.2629 + {
1.2630 + if (hir->type()->isInt32() || hir->type()->isEnum()) {
1.2631 + Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.2632 + hir_ = new (pool_) HUnary(node, type, TOK_MINUS, hir);
1.2633 + return;
1.2634 + }
1.2635 + if (hir->type()->isFloat()) {
1.2636 + hir_ = new (pool_) HUnary(node, hir->type(), TOK_MINUS, hir);
1.2637 + return;
1.2638 + }
1.2639 +
1.2640 + char name[255];
1.2641 + cc_.reportError(node->pos(), Message_InvalidUnaryType,
1.2642 + "-",
1.2643 + GetTypeName(hir->type(), name, sizeof(name)));
1.2644 + break;
1.2645 + }
1.2646 +
1.2647 + default:
1.2648 + {
1.2649 + assert(node->token() == TOK_LABEL);
1.2650 +
1.2651 + TypeSymbol *sym = node->tag()->sym()->asType();
1.2652 + if (!sym) {
1.2653 + cc_.reportError(node->pos(), Message_IdentifierIsNotAType,
1.2654 + sym->name()->chars());
1.2655 + return;
1.2656 + }
1.2657 +
1.2658 + if (!IsValidUncheckedType(sym->effective())) {
1.2659 + char name[255];
1.2660 + cc_.reportError(node->pos(), Message_InvalidUncheckedCastTo,
1.2661 + GetTypeName(sym->type(), name, sizeof(name)));
1.2662 + return;
1.2663 + }
1.2664 + if (!IsValidUncheckedType(hir->type())) {
1.2665 + char name[255];
1.2666 + cc_.reportError(node->pos(), Message_InvalidUncheckedCastFrom,
1.2667 + GetTypeName(hir->type(), name, sizeof(name)));
1.2668 + return;
1.2669 + }
1.2670 +
1.2671 + hir_ = new (pool_) HUnary(node, sym->effective(), TOK_LABEL, hir);
1.2672 + break;
1.2673 + }
1.2674 + }
1.2675 +}
1.2676 +
1.2677 +void
1.2678 +SemanticAnalysis::import(HIR *hir, FieldExpression *node)
1.2679 +{
1.2680 + // Note that we don't care if the hir type is "importable", since we
1.2681 + // can only do anything if the important has a constant binding.
1.2682 + unsigned index = hir->toImport()->index();
1.2683 + Local<Importable> importable(zone_, unit_->module()->getImportAt(index));
1.2684 +
1.2685 + if (importable->isPackage()) {
1.2686 + // Look at what's already loaded and see if anything exists. We
1.2687 + // can't create stuff on-demand here since it's too late to add
1.2688 + // new translation units to the CompileContext.
1.2689 + Local<Package> package(zone_, Package::cast(importable));
1.2690 + Local<Importable> found(zone_, package->import(node->field()));
1.2691 + if (!found) {
1.2692 + cc_.reportError(node->pos(), Message_PackageDoesNotHaveMember, node->field()->chars());
1.2693 + return;
1.2694 + }
1.2695 +
1.2696 + // If we did find something, make sure it is in our import list.
1.2697 + // If we didn't explicitly import it, we have no right to use it.
1.2698 + for (index = 0; index < unit_->module()->imports(); index++) {
1.2699 + if (unit_->module()->getImportAt(index) == importable)
1.2700 + break;
1.2701 + }
1.2702 +
1.2703 + if (index == unit_->module()->imports()) {
1.2704 + cc_.reportError(node->pos(), Message_ImportWasNeverImported, node->field()->chars());
1.2705 + return;
1.2706 + }
1.2707 +
1.2708 + // Just create a new HImport.
1.2709 + hir_ = new (pool_) HImport(node, hir->type(), index);
1.2710 + } else {
1.2711 + // Modules can never have sub-modules or sub-packages.
1.2712 + unsigned index;
1.2713 + Local<Module> module(zone_, Module::cast(importable));
1.2714 + Local<StructMap> map(zone_, module->globals()->map());
1.2715 + Local<Descriptor> desc(zone_, map->type()->lookupField(node->field(), &index));
1.2716 + if (!desc) {
1.2717 + cc_.reportError(node->pos(), Message_FieldNotFound, node->field()->chars());
1.2718 + return;
1.2719 + }
1.2720 + hir_ = new (pool_) HField(node, hir, desc->type(), index);
1.2721 + }
1.2722 +}
1.2723 +
1.2724 +void
1.2725 +SemanticAnalysis::visitFieldExpression(FieldExpression *node)
1.2726 +{
1.2727 + HIR *hir = eval(node->left());
1.2728 + if (!hir)
1.2729 + return;
1.2730 +
1.2731 + if (hir->isImport()) {
1.2732 + import(hir, node);
1.2733 + return;
1.2734 + }
1.2735 +
1.2736 + char name[255];
1.2737 + cc_.reportError(node->pos(), Message_InvalidFieldExpression,
1.2738 + GetTypeName(hir->type(), name, sizeof(name)));
1.2739 +}
1.2740 +
1.2741 +static inline TokenKind
1.2742 +ToCompare(Expression *expr)
1.2743 +{
1.2744 + if (expr->isBinaryExpression()) {
1.2745 + BinaryExpression *b = expr->toBinaryExpression();
1.2746 + if (b->token() >= TOK_EQUALS && b->token() <= TOK_OR)
1.2747 + return b->token();
1.2748 + } else if (expr->isUnaryExpression()) {
1.2749 + UnaryExpression *u = expr->toUnaryExpression();
1.2750 + if (u->token() == TOK_NOT)
1.2751 + return TOK_NOT;
1.2752 + }
1.2753 + return TOK_EOF;
1.2754 +}
1.2755 +
1.2756 +void
1.2757 +SemanticAnalysis::visitForTest(Expression *expr,
1.2758 + Label *trueBranch,
1.2759 + Label *falseBranch,
1.2760 + Label *fallthrough)
1.2761 +{
1.2762 + Local<Type> boolType(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
1.2763 +
1.2764 + TokenKind token = ToCompare(expr);
1.2765 + if (token == TOK_EOF || token == TOK_NOT) {
1.2766 + HIR *hir;
1.2767 + if (token == TOK_EOF)
1.2768 + hir = eval(expr);
1.2769 + else
1.2770 + hir = eval(expr->toUnaryExpression()->expression());
1.2771 + if (!hir)
1.2772 + return;
1.2773 + if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
1.2774 + return;
1.2775 +
1.2776 + discharge(hir);
1.2777 +
1.2778 + bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
1.2779 + Opcode op = jumpOnTrue ? OP_JT : OP_JF;
1.2780 +
1.2781 + if (fallthrough == falseBranch)
1.2782 + __ j(op, trueBranch);
1.2783 + else
1.2784 + __ j(op, falseBranch);
1.2785 + return;
1.2786 + }
1.2787 +
1.2788 + BinaryExpression *bin = expr->toBinaryExpression();
1.2789 + if (token == TOK_AND || token == TOK_OR) {
1.2790 + Label next;
1.2791 + if (token == TOK_AND)
1.2792 + visitForTest(bin->left(), &next, falseBranch, &next);
1.2793 + else
1.2794 + visitForTest(bin->left(), trueBranch, &next, &next);
1.2795 + __ bind(&next);
1.2796 + visitForTest(bin->right(), trueBranch, falseBranch, fallthrough);
1.2797 + return;
1.2798 + }
1.2799 +
1.2800 + HIR *left = eval(bin->left());
1.2801 + HIR *right = eval(bin->right());
1.2802 + if (!left || !right)
1.2803 + return;
1.2804 +
1.2805 + HIR *hir = binary(bin, bin->token(), left, right);
1.2806 + if (!hir)
1.2807 + return;
1.2808 + if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
1.2809 + return;
1.2810 +
1.2811 + discharge(hir);
1.2812 + if (fallthrough == trueBranch)
1.2813 + __ j(OP_JF, falseBranch);
1.2814 + else
1.2815 + __ j(OP_JT, trueBranch);
1.2816 +}
1.2817 +
1.2818 +HLValue *
1.2819 +SemanticAnalysis::lvalue(Expression *expr)
1.2820 +{
1.2821 + HIR *hir = eval(expr);
1.2822 + if (!hir)
1.2823 + return NULL;
1.2824 +
1.2825 + if (!hir->isLValue()) {
1.2826 + cc_.reportError(expr->pos(), Message_ExpectedLValue);
1.2827 + return NULL;
1.2828 + }
1.2829 +
1.2830 + return static_cast<HLValue *>(hir);
1.2831 +}
1.2832 +
1.2833 +HIR *
1.2834 +SemanticAnalysis::eval(Expression *expr)
1.2835 +{
1.2836 + assert(!hir_);
1.2837 + expr->accept(this);
1.2838 +
1.2839 + HIR *hir = hir_;
1.2840 + hir_ = NULL;
1.2841 +
1.2842 + return hir;
1.2843 +}
1.2844 +
1.2845 +void
1.2846 +SemanticAnalysis::discharge(HIR *hir)
1.2847 +{
1.2848 + EmitHIR(zone_, emitter_, hir);
1.2849 +}