Remove calls to ZONE().
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
7 * JITCraft 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)
12 * Foobar 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.
16 * You should have received a copy of the GNU General Public License along with
17 * JITCraft. If not, see http://www.gnu.org/licenses/.
19 #include "BytecodeCompiler.h"
29 typedef BytecodeEmitter::Label Label;
33 BytecodeCompiler::BytecodeCompiler(Zone *zone, ParseTree *tree, Module *module)
43 static inline TokenKind
44 ToCompare(Expression *expr)
46 if (expr->isBinaryExpression()) {
47 BinaryExpression *b = expr->toBinaryExpression();
48 if (b->token() >= TOK_EQUALS && b->token() <= TOK_GE)
55 CompareTokenToJump(TokenKind kind)
69 assert(kind == TOK_LE);
75 TokenToOpcode(TokenKind kind)
97 assert(kind == TOK_BITXOR);
103 BytecodeCompiler::recordLifoSlot(Scope *scope)
108 if (Variable *var = scope->lifoSlot()) {
109 locals_->set(zone_, var->slot(), var->type());
110 __ savelifo(var->slot());
115 BytecodeCompiler::unwindTo(Scope *scope)
117 // Note: we only need to unwind to the outermost scope's LIFO slot.
118 Variable *var = NULL;
119 for (Scope *current = scope_; current != scope; current = current->enclosing()) {
120 if (Variable *slot = current->lifoSlot())
125 __ unwindlifo(var->slot());
129 BytecodeCompiler::visit(NameProxy *name)
131 switch (name->binding()->kind()) {
132 case BoundName::VARIABLE:
134 Variable *var = name->binding()->toVariable();
136 if (var->location() == Variable::STACK) {
137 __ getlocal(var->slot());
138 assert(!name->type()->isReference());
140 assert(var->location() == Variable::PARAMETER);
141 __ getarg(var->slot());
143 // If this argument is actually a reference, dereference it now.
144 if (var->type()->isReference())
145 __ getref(var->type()->contained()->primitive());
152 NamedConstant *constant = name->binding()->toNamedConstant();
153 __ int_(constant->value().toInt());
160 BytecodeCompiler::visit(ExpressionStatement *node)
162 // Expressions leave their value on the top of the stack, so we make sure
163 // to balance the stack if they're used as a statement.
164 node->expression()->accept(this);
169 BytecodeCompiler::visit(Assignment *node)
171 // The first step is three sub-steps:
173 // (1) Bind the left-hand side.
174 // -- If a cumulative operation (+=, etc):
175 // (2) Save a copy of the binding on the stack.
176 // (3) Dereference the binding to get a value.
178 if (node->lvalue()->isNameProxy()) {
179 NameProxy *proxy = node->lvalue()->toNameProxy();
180 Variable *var = proxy->binding()->toVariable();
183 if (var->type()->isReference() || var->type()->isArray())
186 // Get the value if needed.
187 if (node->token() != TOK_ASSIGN) {
188 // += etc is not allowed on arrays.
189 assert(!var->type()->isArray());
191 if (var->type()->isReference()) {
193 __ getref(var->type()->contained()->primitive());
199 IndexExpression *index = node->lvalue()->toIndexExpression();
201 // Note: Eventually, watch out for a whole here. An expression like:
203 // (a[4] = (5, a = []))
205 // Could shrink array, so we need to either bind a[i] to a Reference,
206 // or keep the bounds check near the set. This is just a semantic
208 index->left()->accept(this);
209 index->right()->accept(this);
211 if (node->token() != TOK_ASSIGN) {
214 if (node->type()->isArray())
217 __ getarray(node->type()->primitive());
221 if (node->token() == TOK_ASSIGN) {
222 node->expression()->accept(this);
224 visitForALU(node->type(), node->expression());
226 TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
227 __ binary(TokenToOpcode(alu));
231 if (node->expression()->type()->isArray()) {
232 // Unlike references, which can only be computed from a NamePRoxy,
233 // arrays can be computed from multiple lvalue types.
235 } else if (node->lvalue()->isNameProxy()) {
236 NameProxy *proxy = node->lvalue()->toNameProxy();
237 Variable *var = proxy->binding()->toVariable();
239 if (var->type()->isReference())
240 __ setref(var->type()->contained()->primitive());
244 IndexExpression *index = node->lvalue()->toIndexExpression();
245 // :TODO: get rid of the BOUNDS instruction, embed it in g/setarray*?
246 // We can't emit it here because the stack is slightly out of position.
248 __ setarray(index->left()->type()->contained()->primitive());
253 BytecodeCompiler::visit(IncDecExpression *node)
255 // In the postfix case, the logic looks like:
257 // (2) Dup -> REF REF
258 // (3) Fetch -> REF VAL
259 // (4) Swap -> VAL REF
260 // (5) Pick -> VAL REF VAL
261 // (6) Add -> VAL REF VAL+1
262 // (7) Store -> VAL VAL+1
265 // In the prefix case, the logic looks like:
267 // (2) Dup -> REF REF
268 // (3) Fetch -> REF VAL
271 // (6) Add -> REF VAL+1
272 // (7) Store -> VAL+1
275 // This is squirrely enough such that we don't bother sharing too much
278 // Note: We simulate a "Pick" operation with a dup2+pop.
280 // This is steps (1) to (5).
281 Expression *expr = node->expression();
282 if (expr->isNameProxy()) {
283 NameProxy *proxy = expr->toNameProxy();
284 Variable *var = proxy->binding()->toVariable();
287 if (var->type()->isReference() || var->type()->isArray())
291 if (var->type()->isReference()) {
293 __ getref(node->type()->primitive());
294 if (node->postfix()) {
299 assert(!var->type()->isArray());
305 IndexExpression *index = expr->toIndexExpression();
306 index->left()->accept(this);
307 index->right()->accept(this);
309 assert(!node->type()->isArray());
312 __ getarray(node->type()->primitive());
314 if (node->postfix()) {
315 // The stack looks like this now:
318 // So we must use a PICK operation to rotate the stack into position.
319 __ roll3(); // INDEX VALUE ARRAY
320 __ roll3(); // VALUE ARRAY INDEX
321 __ pick3(); // VALUE ARRAY INDEX VALUE
326 if (node->type()->isFloat()) {
329 assert(node->type()->isInt32());
333 if (node->token() == TOK_INCREMENT)
339 if (expr->isNameProxy()) {
340 NameProxy *proxy = expr->toNameProxy();
341 Variable *var = proxy->binding()->toVariable();
343 if (var->type()->isReference())
344 __ setref(node->type()->primitive());
348 __ setarray(node->type()->primitive());
357 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
360 if (needed->isFloat() && !node->type()->isFloat())
363 assert(needed->primitive() == node->type()->primitive());
367 BytecodeCompiler::visit(BinaryExpression *node)
369 visitForALU(node->type(), node->left());
370 visitForALU(node->type(), node->right());
372 Opcode op = TokenToOpcode(node->token());
373 if (node->type()->isFloat())
374 op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
379 BytecodeCompiler::visit(IndexExpression *node)
381 node->left()->accept(this);
382 node->right()->accept(this);
385 if (node->type()->isArray())
388 __ getarray(node->type()->primitive());
392 BytecodeCompiler::visit(ReturnStatement *node)
394 if (node->expression())
395 node->expression()->accept(this);
403 BytecodeCompiler::visitForTest(Expression *expression, Label *label, bool onTrue)
405 TokenKind token = ToCompare(expression);
406 if (token == TOK_EOF) {
407 expression->accept(this);
415 Opcode op = CompareTokenToJump(token);
419 assert(expression->isBinaryExpression());
420 BinaryExpression *binary = expression->toBinaryExpression();
421 binary->left()->accept(this);
422 binary->right()->accept(this);
427 BytecodeCompiler::visit(ForStatement *node)
429 AutoEnterScope forScope(this, node->scope());
431 recordLifoSlot(node->scope());
434 LoopScope loop(scope_, &join, &update, &loop_);
436 if (node->initialization())
437 node->initialization()->accept(this);
440 if (node->condition())
444 node->body()->accept(this);
448 node->update()->accept(this);
450 if (node->condition()) {
452 visitForTest(node->condition(), &header, true);
460 unwindTo(node->scope()->enclosing());
461 assert(__ stackDepth() == 0);
465 BytecodeCompiler::visit(WhileStatement *node)
471 LoopScope loop(scope_, &join, &header, &loop_);
473 if (node->token() == TOK_WHILE) {
474 visitForTest(node->condition(), &join, false);
475 node->body()->accept(this);
478 node->body()->accept(this);
479 visitForTest(node->condition(), &header, true);
486 BytecodeCompiler::visit(BreakStatement *node)
488 unwindTo(loop_->scope());
489 __ jump(loop_->break_());
493 BytecodeCompiler::visit(ContinueStatement *node)
495 unwindTo(loop_->scope());
496 __ jump(loop_->continue_());
500 BytecodeCompiler::visit(BlockStatement *node)
502 AutoEnterScope blockScope(this, node->scope());
504 recordLifoSlot(node->scope());
506 for (size_t i = 0; i < node->statements()->length(); i++) {
507 Statement *statement = node->statements()->at(i);
508 statement->accept(this);
509 assert(__ stackDepth() == 0);
512 // We don't bother emitting an "unwind" instruction for function scopes,
513 // since this is taken care of by the calling convention.
514 if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
515 unwindTo(node->scope()->enclosing());
519 BytecodeCompiler::visit(IntegerLiteral *node)
521 __ int_(node->value());
525 BytecodeCompiler::visit(FloatLiteral *node)
527 __ float_((float)node->value());
530 static inline ArrayMap *
531 BuildArrayMap(Zone *zone, Handle<Type> type)
534 Local<ArrayMap> contained(zone);
535 if (type->levels() > 1) {
536 Local<Type> containedType(zone, type->contained());
537 contained = BuildArrayMap(zone, containedType);
542 return ArrayMap::New(zone, type, contained);
546 BytecodeCompiler::visit(StringLiteral *node)
548 // :TODO: remove this Local
549 Local<Type> type(zone_, node->type());
550 Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
554 Local<Array> array(zone_, Array::New(zone_, map, node->string()->length(), Heap::Tenure_Old));
558 assert(array->nelements() >= node->string()->length());
559 memcpy(array->chars(), node->string()->raw(), node->string()->length() * sizeof(char));
565 BytecodeCompiler::visit(VariableDeclaration *node)
567 Variable *var = node->variable();
568 assert(var->location() == Variable::STACK);
570 Local<Type> type(zone_, var->type());
571 if (type->isArray()) {
573 Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
574 __ newarray_lifo(map);
576 if (node->initialization()) {
577 node->initialization()->accept(this);
581 if (node->initialization()) {
582 node->initialization()->accept(this);
584 if (!node->postDimensions())
588 __ setlocal(var->slot());
591 locals_->set(zone_, var->slot(), var->type());
595 BytecodeCompiler::visit(CallExpression *node)
598 Type *funType = node->callee()->type();
600 for (size_t i = 0; i < node->arguments()->size(); i++) {
601 Expression *arg = node->arguments()->at(i);
603 Type *given = arg->type();
604 Type *actual = Type::cast(funType->parameters()->at(i));
605 if (actual->isReference()) {
606 if (given->isReference()) {
607 // The input type is already a reference, so we're just passing
608 // it on to the callee.
610 } else if (arg->isNameProxy()) {
611 // :TODO: test with functions and globals
612 // Compute a reference to the name.
613 Variable *var = arg->toNameProxy()->binding()->toVariable();
615 } else if (arg->isIndexExpression()) {
616 IndexExpression *expr = arg->toIndexExpression();
617 expr->left()->accept(this);
618 expr->right()->accept(this);
622 // We don't know how to, or can't, build a direct reference to
623 // this type. Make an indirect one, by taking the top of the
624 // stack and boxing it up.
633 __ callglobal(node->arguments()->size(), 0);
637 BytecodeCompiler::visit(IfStatement *node)
639 if (!node->ifFalse()) {
641 visitForTest(node->condition(), &fail, false);
642 node->ifTrue()->accept(this);
646 visitForTest(node->condition(), &fail, false);
647 node->ifTrue()->accept(this);
650 node->ifFalse()->accept(this);
656 BytecodeCompiler::visit(FunctionStatement *node)
658 BytecodeCompiler child(zone_, tree_, module_);
659 Function *fun = child.compileFunction(module_, node);
663 assert(!module_->getFunction(node->fun()->slot()));
664 module_->setFunction(zone_, node->fun()->slot(), fun);
668 BytecodeCompiler::visit(EnumStatement *node)
670 // :TODO: eventually, we'll export these.
674 BytecodeCompiler::compileFunction(Module *module, FunctionStatement *node)
676 // Note: No need to record a life slot here, since it's part of the Frame.
677 AutoEnterScope functionScope(this, node->scope());
680 locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
682 node->body()->accept(this);
689 ByteArray *bytes = ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old);
692 memcpy(bytes->raw(), __ buffer(), __ length());
694 unsigned nargs = node->scope()->numArguments();
695 FixedArray *args = FixedArray::New(zone_, nargs, Heap::Tenure_Old);
699 for (size_t i = 0; i < node->scope()->numArguments(); i++)
700 args->set(zone_, i, node->scope()->getArgument(i)->type());
702 for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
703 assert(locals_->at(i));
705 FixedArray *objects = FixedArray::New(zone_, __ objects()->size(), Heap::Tenure_Old);
709 for (size_t i = 0; i < __ objects()->size(); i++)
710 objects->set(zone_, i, __ objects()->at(i));
712 Code *code = Code::New(zone_, bytes, locals_, objects, __ maxStackDepth(), module_);
716 Function *fun = Function::New(zone_, module_, code, node->fun()->type(), node->pos());
724 BytecodeCompiler::compile()
727 module_ = Module::New(zone_, tree_->scope()->numFunctions());
731 for (size_t i = 0; i < tree_->statements()->length(); i++) {
732 Statement *statement = tree_->statements()->at(i);
733 statement->accept(this);
737 for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
738 assert(module_->getFunction(i));