Add support for float variables and basic math.
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"
25 typedef BytecodeEmitter::Label Label;
29 BytecodeCompiler::BytecodeCompiler(ParseTree *tree)
35 static inline TokenKind
36 ToCompare(Expression *expr)
38 if (expr->isBinaryExpression()) {
39 BinaryExpression *b = expr->toBinaryExpression();
40 if (b->token() >= TOK_EQUALS && b->token() <= TOK_GE)
47 CompareTokenToJump(TokenKind kind)
68 TokenToOpcode(TokenKind kind)
85 BytecodeCompiler::leaveScope(Scope *scope)
90 if (Variable *var = scope->firstUnsafeArray())
91 __ unwind(var->slot());
95 BytecodeCompiler::visit(NameProxy *name)
97 switch (name->binding()->kind()) {
98 case BoundName::VARIABLE:
100 Variable *var = name->binding()->toVariable();
102 if (var->location() == Variable::STACK) {
103 __ getlocal(var->slot());
105 assert(var->location() == Variable::PARAMETER);
106 __ getarg(var->slot());
113 NamedConstant *constant = name->binding()->toNamedConstant();
114 __ int_(constant->value().toInt());
121 BytecodeCompiler::visit(ExpressionStatement *node)
123 // Expressions leave their value on the top of the stack, so we make sure
124 // to balance the stack if they're used as a statement.
125 node->expression()->accept(this);
130 BytecodeCompiler::visit(Assignment *node)
132 if (node->lvalue()->isNameProxy()) {
133 NameProxy *proxy = node->lvalue()->toNameProxy();
134 Variable *var = proxy->binding()->toVariable();
136 node->expression()->accept(this);
137 if (var->location() == Variable::STACK) {
138 __ setlocal(var->slot());
140 assert(var->location() == Variable::PARAMETER);
141 __ setarg(var->slot());
143 } else if (node->lvalue()->isIndexExpression()) {
144 IndexExpression *index = node->lvalue()->toIndexExpression();
146 index->left()->accept(this);
147 index->right()->accept(this);
149 node->expression()->accept(this);
155 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
158 if (needed->isFloat() && !node->type()->isFloat())
163 BytecodeCompiler::visit(BinaryExpression *node)
165 visitForALU(node->type(), node->left());
166 visitForALU(node->type(), node->right());
168 Opcode op = TokenToOpcode(node->token());
169 if (node->type()->isFloat())
170 op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
175 BytecodeCompiler::visit(IndexExpression *node)
177 node->left()->accept(this);
178 node->right()->accept(this);
181 if (node->type()->isArray())
188 BytecodeCompiler::visit(ReturnStatement *node)
190 if (node->expression())
191 node->expression()->accept(this);
199 BytecodeCompiler::visitForTest(Expression *expression, Label *label, bool onTrue)
201 TokenKind token = ToCompare(expression);
202 if (token == TOK_EOF) {
203 expression->accept(this);
211 Opcode op = CompareTokenToJump(token);
215 assert(expression->isBinaryExpression());
216 BinaryExpression *binary = expression->toBinaryExpression();
217 binary->left()->accept(this);
218 binary->right()->accept(this);
223 BytecodeCompiler::visit(ForStatement *node)
225 AutoEnterScope forScope(this, node->scope());
227 if (node->declaration())
228 node->declaration()->accept(this);
231 if (node->condition())
235 node->body()->accept(this);
238 node->update()->accept(this);
240 if (node->condition()) {
242 visitForTest(node->condition(), &header, true);
247 leaveScope(node->scope());
248 assert(__ stackDepth() == 0);
252 BytecodeCompiler::visit(BlockStatement *node)
254 AutoEnterScope blockScope(this, node->scope());
256 for (size_t i = 0; i < node->statements()->length(); i++) {
257 Statement *statement = node->statements()->at(i);
258 statement->accept(this);
259 assert(__ stackDepth() == 0);
262 // We don't bother emitting an "unwind" instruction for function scopes,
263 // since this is taken care of by the calling convention.
264 if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
265 leaveScope(node->scope());
269 BytecodeCompiler::visit(IntegerLiteral *node)
271 __ int_(node->value());
275 BytecodeCompiler::visit(FloatLiteral *node)
277 __ float_((float)node->value());
281 BytecodeCompiler::visit(VariableDeclaration *node)
283 Variable *var = node->variable();
284 assert(var->location() == Variable::STACK);
286 Type *type = var->type();
287 if (type->isArray()) {
288 bool isConstant = true;
289 for (Type *child = type; child->isArray(); child = child->contained()) {
290 if (child->elements() == Type::UNKNOWN_SIZE) {
297 for (size_t i = 0; i < node->postDimensions()->size(); i++) {
298 Expression *expr = node->postDimensions()->at(i);
305 if (node->initialization()) {
306 node->initialization()->accept(this);
308 if (!node->postDimensions())
312 __ setlocal(var->slot());
315 locals_[var->slot()] = var->type();
319 BytecodeCompiler::visit(CallExpression *node)
321 NameProxy *fun = node->callee()->toNameProxy();
323 for (size_t i = 0; i < node->arguments()->size(); i++) {
324 Expression *arg = node->arguments()->at(i);
328 __ callglobal(node->arguments()->size(), 0);
332 BytecodeCompiler::visit(IfStatement *node)
334 if (!node->ifFalse()) {
336 visitForTest(node->condition(), &fail, false);
337 node->ifTrue()->accept(this);
341 visitForTest(node->condition(), &fail, false);
342 node->ifTrue()->accept(this);
345 node->ifFalse()->accept(this);
351 BytecodeCompiler::visit(FunctionStatement *node)
353 BytecodeCompiler child(tree_);
354 Code *code = child.compileFunction(module_, node);
356 assert(!module_->getFunction(node->fun()->slot()));
357 module_->setFunction(node->fun()->slot(), code);
361 BytecodeCompiler::visit(EnumStatement *node)
363 // :TODO: eventually, we'll export these.
367 BytecodeCompiler::compileFunction(Module *module, FunctionStatement *node)
369 AutoEnterScope functionScope(this, node->scope());
371 locals_ = new Type *[node->scope()->maxContainedLocals()];
372 memset(locals_, 0, sizeof(Type *) * node->scope()->maxContainedLocals());
374 node->body()->accept(this);
381 bytecode *start = (bytecode *)malloc(__ length() * sizeof(bytecode));
382 memcpy(start, __ buffer(), __ length());
384 unsigned nargs = node->scope()->numArguments();
385 Type **args = new Type *[nargs];
386 for (size_t i = 0; i < node->scope()->numArguments(); i++)
387 args[i] = node->scope()->getArgument(i)->type();
389 for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
392 Code *code = new Code(module,
398 node->scope()->maxContainedLocals(),
405 BytecodeCompiler::compile()
407 Code **functions = new Code *[tree_->scope()->numFunctions()];
408 memset(functions, 0, sizeof(Code *) * tree_->scope()->numFunctions());
410 module_ = new Module(functions, tree_->scope()->numFunctions());
412 for (size_t i = 0; i < tree_->statements()->length(); i++) {
413 Statement *statement = tree_->statements()->at(i);
414 statement->accept(this);
418 for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
419 assert(functions[i]);