Added initial String: support.
2 * Copyright (C) 2012 David Anderson
4 * This file is part of JITCraft.
6 * JITCraft is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
11 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * JITCraft. If not, see http://www.gnu.org/licenses/.
18 #include "BytecodeCompiler.h"
28 typedef BytecodeEmitter::Label Label;
32 BytecodeCompiler::BytecodeCompiler(ParseTree *tree, Module *module)
40 static inline TokenKind
41 ToCompare(Expression *expr)
43 if (expr->isBinaryExpression()) {
44 BinaryExpression *b = expr->toBinaryExpression();
45 if (b->token() >= TOK_EQUALS && b->token() <= TOK_GE)
52 CompareTokenToJump(TokenKind kind)
73 TokenToOpcode(TokenKind kind)
102 BytecodeCompiler::recordLifoSlot(Scope *scope)
107 if (Variable *var = scope->lifoSlot()) {
108 locals_->set(ZONE(), var->slot(), var->type());
109 __ savelifo(var->slot());
114 BytecodeCompiler::unwindTo(Scope *scope)
116 // Note: we only need to unwind to the outermost scope's LIFO slot.
117 Variable *var = NULL;
118 for (Scope *current = scope_; current != scope; current = current->enclosing()) {
119 if (Variable *slot = current->lifoSlot())
124 __ unwindlifo(var->slot());
128 BytecodeCompiler::visit(NameProxy *name)
130 switch (name->binding()->kind()) {
131 case BoundName::VARIABLE:
133 Variable *var = name->binding()->toVariable();
135 if (var->location() == Variable::STACK) {
136 __ getlocal(var->slot());
137 assert(!name->type()->isReference());
139 assert(var->location() == Variable::PARAMETER);
140 __ getarg(var->slot());
142 // If this argument is actually a reference, dereference it now.
143 if (var->type()->isReference()) {
144 if (var->type()->contained()->isFloat()) {
147 assert(var->type()->contained()->isInt32());
157 NamedConstant *constant = name->binding()->toNamedConstant();
158 __ int_(constant->value().toInt());
165 BytecodeCompiler::visit(ExpressionStatement *node)
167 // Expressions leave their value on the top of the stack, so we make sure
168 // to balance the stack if they're used as a statement.
169 node->expression()->accept(this);
174 BytecodeCompiler::visit(Assignment *node)
176 // First compute the left-hand side.
177 if (node->lvalue()->isNameProxy()) {
178 NameProxy *proxy = node->lvalue()->toNameProxy();
179 Variable *var = proxy->binding()->toVariable();
181 // Make sure to bind the left-hand side first.
182 if (var->type()->isReference() || var->type()->isArray())
185 node->expression()->accept(this);
186 } else if (node->lvalue()->isIndexExpression()) {
187 IndexExpression *index = node->lvalue()->toIndexExpression();
189 // Note: Eventually, watch out for a whole here. An expression like:
191 // (a[4] = (5, a = []))
193 // Could shrink array, so we need to either bind a[i] to a Reference,
194 // or keep the bounds check near the set. This is just a semantic
196 index->left()->accept(this);
197 index->right()->accept(this);
198 node->expression()->accept(this);
202 if (node->expression()->type()->isArray()) {
203 // Unlike references, which can only be computed from a NamePRoxy,
204 // arrays can be computed from multiple lvalue types.
206 } else if (node->lvalue()->isNameProxy()) {
207 NameProxy *proxy = node->lvalue()->toNameProxy();
208 Variable *var = proxy->binding()->toVariable();
210 if (var->type()->isReference()) {
211 if (var->type()->contained()->isFloat()) {
214 assert(var->type()->contained()->isInt32());
221 IndexExpression *index = node->lvalue()->toIndexExpression();
223 __ setarray(index->left()->type()->contained()->primitive());
228 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
231 if (needed->isFloat() && !node->type()->isFloat())
236 BytecodeCompiler::visit(BinaryExpression *node)
238 visitForALU(node->type(), node->left());
239 visitForALU(node->type(), node->right());
241 Opcode op = TokenToOpcode(node->token());
242 if (node->type()->isFloat())
243 op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
248 BytecodeCompiler::visit(IndexExpression *node)
250 node->left()->accept(this);
251 node->right()->accept(this);
254 if (node->type()->isArray())
257 __ getarray(node->type()->primitive());
261 BytecodeCompiler::visit(ReturnStatement *node)
263 if (node->expression())
264 node->expression()->accept(this);
272 BytecodeCompiler::visitForTest(Expression *expression, Label *label, bool onTrue)
274 TokenKind token = ToCompare(expression);
275 if (token == TOK_EOF) {
276 expression->accept(this);
284 Opcode op = CompareTokenToJump(token);
288 assert(expression->isBinaryExpression());
289 BinaryExpression *binary = expression->toBinaryExpression();
290 binary->left()->accept(this);
291 binary->right()->accept(this);
296 BytecodeCompiler::visit(ForStatement *node)
298 AutoEnterScope forScope(this, node->scope());
300 recordLifoSlot(node->scope());
303 LoopScope loop(scope_, &join, &update, &loop_);
305 if (node->declaration())
306 node->declaration()->accept(this);
309 if (node->condition())
313 node->body()->accept(this);
317 node->update()->accept(this);
319 if (node->condition()) {
321 visitForTest(node->condition(), &header, true);
329 unwindTo(node->scope()->enclosing());
330 assert(__ stackDepth() == 0);
334 BytecodeCompiler::visit(WhileStatement *node)
340 LoopScope loop(scope_, &join, &header, &loop_);
342 if (node->token() == TOK_WHILE) {
343 visitForTest(node->condition(), &join, false);
344 node->body()->accept(this);
347 node->body()->accept(this);
348 visitForTest(node->condition(), &header, true);
355 BytecodeCompiler::visit(BreakStatement *node)
357 unwindTo(loop_->scope());
358 __ jump(loop_->break_());
362 BytecodeCompiler::visit(ContinueStatement *node)
364 unwindTo(loop_->scope());
365 __ jump(loop_->continue_());
369 BytecodeCompiler::visit(BlockStatement *node)
371 AutoEnterScope blockScope(this, node->scope());
373 recordLifoSlot(node->scope());
375 for (size_t i = 0; i < node->statements()->length(); i++) {
376 Statement *statement = node->statements()->at(i);
377 statement->accept(this);
378 assert(__ stackDepth() == 0);
381 // We don't bother emitting an "unwind" instruction for function scopes,
382 // since this is taken care of by the calling convention.
383 if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
384 unwindTo(node->scope()->enclosing());
388 BytecodeCompiler::visit(IntegerLiteral *node)
390 __ int_(node->value());
394 BytecodeCompiler::visit(FloatLiteral *node)
396 __ float_((float)node->value());
399 static inline ArrayMap *
400 BuildArrayMap(Zone *zone, Type *type)
403 ArrayMap *contained = NULL;
404 if (type->levels() > 1) {
405 contained = BuildArrayMap(zone, type->contained());
410 return ArrayMap::New(zone, type, contained);
414 BytecodeCompiler::visit(StringLiteral *node)
417 ArrayMap *map = BuildArrayMap(ZONE(), node->type());
421 Array *array = Array::New(ZONE(), map, node->string()->length(), Heap::Tenure_Old);
425 assert(array->nelements() >= node->string()->length());
426 memcpy(array->chars(), node->string()->raw(), node->string()->length() * sizeof(char));
432 BytecodeCompiler::visit(VariableDeclaration *node)
434 Variable *var = node->variable();
435 assert(var->location() == Variable::STACK);
437 Type *type = var->type();
438 if (type->isArray()) {
440 ArrayMap *map = BuildArrayMap(ZONE(), type);
441 __ newarray_lifo(map);
443 if (node->initialization()) {
444 node->initialization()->accept(this);
448 if (node->initialization()) {
449 node->initialization()->accept(this);
451 if (!node->postDimensions())
455 __ setlocal(var->slot());
458 locals_->set(ZONE(), var->slot(), var->type());
462 BytecodeCompiler::visit(CallExpression *node)
464 NameProxy *fun = node->callee()->toNameProxy();
467 Type *funType = node->callee()->type();
469 for (size_t i = 0; i < node->arguments()->size(); i++) {
470 Expression *arg = node->arguments()->at(i);
472 Type *given = arg->type();
473 Type *actual = Type::cast(funType->parameters()->at(i));
474 if (actual->isReference()) {
475 if (given->isReference()) {
476 // The input type is already a reference, so we're just passing
477 // it on to the callee.
479 } else if (arg->isNameProxy()) {
480 // :TODO: test with functions and globals
481 // Compute a reference to the name.
482 Variable *var = arg->toNameProxy()->binding()->toVariable();
484 } else if (arg->isIndexExpression()) {
485 IndexExpression *expr = arg->toIndexExpression();
486 expr->left()->accept(this);
487 expr->right()->accept(this);
491 // We don't know how to, or can't, build a direct reference to
492 // this type. Make an indirect one, by taking the top of the
493 // stack and boxing it up.
502 __ callglobal(node->arguments()->size(), 0);
506 BytecodeCompiler::visit(IfStatement *node)
508 if (!node->ifFalse()) {
510 visitForTest(node->condition(), &fail, false);
511 node->ifTrue()->accept(this);
515 visitForTest(node->condition(), &fail, false);
516 node->ifTrue()->accept(this);
519 node->ifFalse()->accept(this);
525 BytecodeCompiler::visit(FunctionStatement *node)
527 BytecodeCompiler child(tree_, module_);
528 Code *code = child.compileFunction(module_, node);
530 assert(!module_->getFunction(node->fun()->slot()));
531 module_->setFunction(ZONE(), node->fun()->slot(), code);
535 BytecodeCompiler::visit(EnumStatement *node)
537 // :TODO: eventually, we'll export these.
541 BytecodeCompiler::compileFunction(Module *module, FunctionStatement *node)
543 // Note: No need to record a life slot here, since it's part of the Frame.
544 AutoEnterScope functionScope(this, node->scope());
547 locals_ = FixedArray::New(ZONE(), node->scope()->maxContainedLocals(), Heap::Tenure_Old);
549 node->body()->accept(this);
556 ByteArray *bytes = ByteArray::New(ZONE(), __ length() * sizeof(bytecode), Heap::Tenure_Old);
559 memcpy(bytes->raw(), __ buffer(), __ length());
561 unsigned nargs = node->scope()->numArguments();
562 FixedArray *args = FixedArray::New(ZONE(), nargs, Heap::Tenure_Old);
566 for (size_t i = 0; i < node->scope()->numArguments(); i++)
567 args->set(ZONE(), i, node->scope()->getArgument(i)->type());
569 for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
570 assert(locals_->at(i));
572 FixedArray *objects = FixedArray::New(ZONE(), __ objects()->size(), Heap::Tenure_Old);
576 for (size_t i = 0; i < __ objects()->size(); i++)
577 objects->set(ZONE(), i, __ objects()->at(i));
579 Code *code = Code::New(ZONE(), bytes, locals_, args, objects, __ maxStackDepth(), module_);
584 BytecodeCompiler::compile()
587 module_ = Module::New(ZONE(), tree_->scope()->numFunctions());
591 for (size_t i = 0; i < tree_->statements()->length(); i++) {
592 Statement *statement = tree_->statements()->at(i);
593 statement->accept(this);
597 for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
598 assert(module_->getFunction(i));