Initial import of some kind of API.
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"
30 typedef BytecodeEmitter::Label Label;
34 BytecodeCompiler::BytecodeCompiler(Zone *zone, ParseTree *tree, Module *module)
37 emitter_(zone->pool()),
45 static inline TokenKind
46 ToCompare(Expression *expr)
48 if (expr->isBinaryExpression()) {
49 BinaryExpression *b = expr->toBinaryExpression();
50 if (b->token() >= TOK_EQUALS && b->token() <= TOK_GE)
57 CompareTokenToJump(TokenKind kind)
71 assert(kind == TOK_LE);
77 TokenToOpcode(TokenKind kind)
99 assert(kind == TOK_BITXOR);
105 BytecodeCompiler::recordLifoSlot(Scope *scope)
110 if (Variable *var = scope->lifoSlot()) {
111 locals_->set(zone_, var->slot(), var->type());
112 __ savelifo(var->slot());
117 BytecodeCompiler::unwindTo(Scope *scope)
119 // Note: we only need to unwind to the outermost scope's LIFO slot.
120 Variable *var = NULL;
121 for (Scope *current = scope_; current != scope; current = current->enclosing()) {
122 if (Variable *slot = current->lifoSlot())
127 __ unwindlifo(var->slot());
131 BytecodeCompiler::visit(NameProxy *name)
133 switch (name->binding()->kind()) {
134 case BoundName::VARIABLE:
136 Variable *var = name->binding()->toVariable();
138 if (var->location() == Variable::STACK) {
140 assert(!name->type()->isReference());
142 assert(var->location() == Variable::PARAMETER);
145 // If this argument is actually a reference, dereference it now.
146 if (var->type()->isReference())
147 __ getref(var->type()->contained()->primitive());
154 NamedConstant *constant = name->binding()->toNamedConstant();
155 __ int_(constant->value().toInt());
162 BytecodeCompiler::visit(ExpressionStatement *node)
164 // Expressions leave their value on the top of the stack, so we make sure
165 // to balance the stack if they're used as a statement.
166 node->expression()->accept(this);
171 BytecodeCompiler::visit(Assignment *node)
173 // The first step is three sub-steps:
175 // (1) Bind the left-hand side.
176 // -- If a cumulative operation (+=, etc):
177 // (2) Save a copy of the binding on the stack.
178 // (3) Dereference the binding to get a value.
180 if (node->lvalue()->isNameProxy()) {
181 NameProxy *proxy = node->lvalue()->toNameProxy();
182 Variable *var = proxy->binding()->toVariable();
185 if (var->type()->isReference() || var->type()->isArray())
188 // Get the value if needed.
189 if (node->token() != TOK_ASSIGN) {
190 // += etc is not allowed on arrays.
191 assert(!var->type()->isArray());
193 if (var->type()->isReference()) {
195 __ getref(var->type()->contained()->primitive());
201 IndexExpression *index = node->lvalue()->toIndexExpression();
203 // Note: Eventually, watch out for a whole here. An expression like:
205 // (a[4] = (5, a = []))
207 // Could shrink array, so we need to either bind a[i] to a Reference,
208 // or keep the bounds check near the set. This is just a semantic
210 index->left()->accept(this);
211 index->right()->accept(this);
213 if (node->token() != TOK_ASSIGN) {
216 if (node->type()->isArray())
219 __ getarray(node->type()->primitive());
223 if (node->token() == TOK_ASSIGN) {
224 node->expression()->accept(this);
226 visitForALU(node->type(), node->expression());
228 TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
229 __ binary(TokenToOpcode(alu));
233 if (node->expression()->type()->isArray()) {
234 // Unlike references, which can only be computed from a NamePRoxy,
235 // arrays can be computed from multiple lvalue types.
237 } else if (node->lvalue()->isNameProxy()) {
238 NameProxy *proxy = node->lvalue()->toNameProxy();
239 Variable *var = proxy->binding()->toVariable();
241 if (var->type()->isReference())
242 __ setref(var->type()->contained()->primitive());
246 IndexExpression *index = node->lvalue()->toIndexExpression();
247 // :TODO: get rid of the BOUNDS instruction, embed it in g/setarray*?
248 // We can't emit it here because the stack is slightly out of position.
250 __ setarray(index->left()->type()->contained()->primitive());
255 BytecodeCompiler::visit(IncDecExpression *node)
257 // In the postfix case, the logic looks like:
259 // (2) Dup -> REF REF
260 // (3) Fetch -> REF VAL
261 // (4) Swap -> VAL REF
262 // (5) Pick -> VAL REF VAL
263 // (6) Add -> VAL REF VAL+1
264 // (7) Store -> VAL VAL+1
267 // In the prefix case, the logic looks like:
269 // (2) Dup -> REF REF
270 // (3) Fetch -> REF VAL
273 // (6) Add -> REF VAL+1
274 // (7) Store -> VAL+1
277 // This is squirrely enough such that we don't bother sharing too much
280 // Note: We simulate a "Pick" operation with a dup2+pop.
282 // This is steps (1) to (5).
283 Expression *expr = node->expression();
284 if (expr->isNameProxy()) {
285 NameProxy *proxy = expr->toNameProxy();
286 Variable *var = proxy->binding()->toVariable();
289 if (var->type()->isReference() || var->type()->isArray())
293 if (var->type()->isReference()) {
295 __ getref(node->type()->primitive());
296 if (node->postfix()) {
301 assert(!var->type()->isArray());
307 IndexExpression *index = expr->toIndexExpression();
308 index->left()->accept(this);
309 index->right()->accept(this);
311 assert(!node->type()->isArray());
314 __ getarray(node->type()->primitive());
316 if (node->postfix()) {
317 // The stack looks like this now:
320 // So we must use a PICK operation to rotate the stack into position.
321 __ roll3(); // INDEX VALUE ARRAY
322 __ roll3(); // VALUE ARRAY INDEX
323 __ pick3(); // VALUE ARRAY INDEX VALUE
328 if (node->type()->isFloat()) {
331 assert(node->type()->isInt32());
335 if (node->token() == TOK_INCREMENT)
341 if (expr->isNameProxy()) {
342 NameProxy *proxy = expr->toNameProxy();
343 Variable *var = proxy->binding()->toVariable();
345 if (var->type()->isReference())
346 __ setref(node->type()->primitive());
350 __ setarray(node->type()->primitive());
359 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
362 if (needed->isFloat() && !node->type()->isFloat())
365 assert(needed->primitive() == node->type()->primitive());
369 BytecodeCompiler::visit(BinaryExpression *node)
371 visitForALU(node->type(), node->left());
372 visitForALU(node->type(), node->right());
374 Opcode op = TokenToOpcode(node->token());
375 if (node->type()->isFloat())
376 op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
381 BytecodeCompiler::visit(IndexExpression *node)
383 node->left()->accept(this);
384 node->right()->accept(this);
387 if (node->type()->isArray())
390 __ getarray(node->type()->primitive());
394 BytecodeCompiler::visit(ReturnStatement *node)
396 if (node->expression())
397 node->expression()->accept(this);
405 BytecodeCompiler::visitForTest(Expression *expression, Label *label, bool onTrue)
407 TokenKind token = ToCompare(expression);
408 if (token == TOK_EOF) {
409 expression->accept(this);
417 Opcode op = CompareTokenToJump(token);
421 assert(expression->isBinaryExpression());
422 BinaryExpression *binary = expression->toBinaryExpression();
423 binary->left()->accept(this);
424 binary->right()->accept(this);
429 BytecodeCompiler::visit(ForStatement *node)
431 AutoEnterScope forScope(this, node->scope());
433 recordLifoSlot(node->scope());
436 LoopScope loop(scope_, &join, &update, &loop_);
438 if (node->initialization())
439 node->initialization()->accept(this);
442 if (node->condition())
446 node->body()->accept(this);
450 node->update()->accept(this);
452 if (node->condition()) {
454 visitForTest(node->condition(), &header, true);
462 unwindTo(node->scope()->enclosing());
463 assert(__ stackDepth() == 0);
467 BytecodeCompiler::visit(WhileStatement *node)
473 LoopScope loop(scope_, &join, &header, &loop_);
475 if (node->token() == TOK_WHILE) {
476 visitForTest(node->condition(), &join, false);
477 node->body()->accept(this);
480 node->body()->accept(this);
481 visitForTest(node->condition(), &header, true);
488 BytecodeCompiler::visit(BreakStatement *node)
490 unwindTo(loop_->scope());
491 __ jump(loop_->break_());
495 BytecodeCompiler::visit(ContinueStatement *node)
497 unwindTo(loop_->scope());
498 __ jump(loop_->continue_());
502 BytecodeCompiler::visit(BlockStatement *node)
504 AutoEnterScope blockScope(this, node->scope());
506 recordLifoSlot(node->scope());
508 for (size_t i = 0; i < node->statements()->length(); i++) {
509 Statement *statement = node->statements()->at(i);
510 statement->accept(this);
511 assert(__ stackDepth() == 0);
514 // We don't bother emitting an "unwind" instruction for function scopes,
515 // since this is taken care of by the calling convention.
516 if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
517 unwindTo(node->scope()->enclosing());
521 BytecodeCompiler::visit(IntegerLiteral *node)
523 __ int_(node->value());
527 BytecodeCompiler::visit(FloatLiteral *node)
529 __ float_((float)node->value());
532 static inline ArrayMap *
533 BuildArrayMap(Zone *zone, Handle<Type> type)
535 Local<ArrayMap> contained(zone);
536 if (type->levels() > 1) {
537 Local<Type> containedType(zone, type->contained());
538 contained = BuildArrayMap(zone, containedType);
543 return ArrayMap::New(zone, type, contained);
547 BytecodeCompiler::visit(StringLiteral *node)
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()) {
572 Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
573 __ newarray_lifo(map);
575 if (node->initialization()) {
576 node->initialization()->accept(this);
580 if (node->initialization()) {
581 node->initialization()->accept(this);
583 if (!node->postDimensions())
590 locals_->set(zone_, var->slot(), var->type());
594 BytecodeCompiler::visit(CallExpression *node)
596 Local<Type> funType(zone_, node->callee()->type());
598 for (size_t i = 0; i < node->arguments()->length(); i++) {
599 Expression *arg = node->arguments()->at(i);
601 Local<Type> given(zone_, arg->type());
602 Local<Type> actual(zone_, Type::cast(funType->parameters()->at(i)));
603 if (actual->isReference()) {
604 if (given->isReference()) {
605 // The input type is already a reference, so we're just passing
606 // it on to the callee.
608 } else if (arg->isNameProxy()) {
609 // :TODO: test with functions and globals
610 // Compute a reference to the name.
611 Variable *var = arg->toNameProxy()->binding()->toVariable();
613 } else if (arg->isIndexExpression()) {
614 IndexExpression *expr = arg->toIndexExpression();
615 expr->left()->accept(this);
616 expr->right()->accept(this);
620 // We don't know how to, or can't, build a direct reference to
621 // this type. Make an indirect one, by taking the top of the
622 // stack and boxing it up.
631 __ callglobal(node->callee()->toNameProxy()->binding()->toNamedFunction()->slot());
632 __ drop(node->arguments()->length());
636 BytecodeCompiler::visit(IfStatement *node)
638 if (!node->ifFalse()) {
640 visitForTest(node->condition(), &fail, false);
641 node->ifTrue()->accept(this);
645 visitForTest(node->condition(), &fail, false);
646 node->ifTrue()->accept(this);
649 node->ifFalse()->accept(this);
655 BytecodeCompiler::visit(FunctionStatement *node)
657 BytecodeCompiler child(zone_, tree_, module_);
658 Local<Function> fun(zone_, child.compileFunction(module_, node));
662 assert(!module_->getFunction(node->fun()->slot()));
663 module_->setFunction(zone_, node->fun()->slot(), fun);
667 BytecodeCompiler::visit(EnumStatement *node)
669 // :TODO: eventually, we'll export these.
673 BytecodeCompiler::compileFunction(Module *module, FunctionStatement *node)
675 // Note: No need to record a life slot here, since it's part of the Frame.
676 AutoEnterScope functionScope(this, node->scope());
678 locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
680 node->body()->accept(this);
687 Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
690 memcpy(bytes->raw(), __ buffer(), __ length());
692 unsigned nargs = node->scope()->numArguments();
693 Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
697 for (size_t i = 0; i < node->scope()->numArguments(); i++)
698 args->set(zone_, i, node->scope()->getArgument(i)->type());
700 for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
701 assert(locals_->at(i));
703 Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
707 for (size_t i = 0; i < __ objects()->length(); i++)
708 objects->set(zone_, i, *(__ objects()->at(i)));
710 Local<ByteArray> safepoints(zone_);
712 // If any stack slots hold gc pointers at potential failure points in the
713 // bytecode, record them now. We do this by building a list of tuples;
714 // each tuple contains the pc offset, and a bitset containing which stack
715 // slots must be scanned by the gc.
716 if (__ oopRecords()->length()) {
717 size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
718 size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
719 safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
723 Address cursor = safepoints->raw();
724 for (size_t i = 0; i < __ oopRecords()->length(); i++) {
725 OopRecord *record = __ oopRecords()->at(i);
726 assert(record->depth <= __ maxStackDepth());
728 *reinterpret_cast<unsigned *>(cursor) = record->offset;
730 unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
731 for (unsigned i = 0; i < record->depth; i++)
732 bits[i / 8] |= (1 << (i % 8));
734 cursor += bytesPerSafepoint;
737 assert(cursor == safepoints->raw() + gcmapSize);
740 Local<Code> code(zone_, Code::New(zone_, bytes, locals_, objects, __ maxStackDepth(), module_,
745 Local<Function> fun(zone_, Function::New(zone_, module_, code, node->fun()->type(), node->pos()));
753 BytecodeCompiler::compile()
755 module_ = Module::New(zone_, tree_->scope()->numFunctions());
759 for (size_t i = 0; i < tree_->statements()->length(); i++) {
760 Statement *statement = tree_->statements()->at(i);
761 statement->accept(this);
765 for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
766 assert(module_->getFunction(i));