jitcraft/BytecodeCompiler.cpp
changeset 0 c455ebb9a5dc
child 1 27f12e2fc369
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/jitcraft/BytecodeCompiler.cpp	Mon Jun 25 02:57:28 2012 -0700
     1.3 @@ -0,0 +1,365 @@
     1.4 +/*
     1.5 + * Copyright (C) 2012 David Anderson
     1.6 + *
     1.7 + * This file is part of JITCraft.
     1.8 + *
     1.9 + * JITCraft is free software: you can redistribute it and/or modify it under
    1.10 + * the terms of the GNU General Public License as published by the Free
    1.11 + * Software Foundation, either version 3 of the License, or (at your option)
    1.12 + * any later version.
    1.13 + * 
    1.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    1.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    1.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License along with
    1.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    1.20 + */
    1.21 +#include "BytecodeCompiler.h"
    1.22 +#include "Scopes.h"
    1.23 +#include "Modules.h"
    1.24 +#include "Types.h"
    1.25 +
    1.26 +using namespace jc;
    1.27 +
    1.28 +typedef BytecodeEmitter::Label Label;
    1.29 +
    1.30 +#define __ emitter_.
    1.31 +
    1.32 +BytecodeCompiler::BytecodeCompiler(ParseTree *tree)
    1.33 +  : tree_(tree)
    1.34 +{
    1.35 +}
    1.36 +
    1.37 +static inline TokenKind
    1.38 +ToCompare(Expression *expr)
    1.39 +{
    1.40 +    if (expr->isBinaryExpression()) {
    1.41 +        BinaryExpression *b = expr->toBinaryExpression();
    1.42 +        if (b->token() >= TOK_EQUALS && b->token() <= TOK_GE)
    1.43 +            return b->token();
    1.44 +    }
    1.45 +    return TOK_EOF;
    1.46 +}
    1.47 +
    1.48 +static inline Opcode
    1.49 +CompareTokenToJump(TokenKind kind)
    1.50 +{
    1.51 +    switch (kind) {
    1.52 +      case TOK_EQUALS:
    1.53 +        return OP_JEQ;
    1.54 +      case TOK_NOTEQUALS:
    1.55 +        return OP_JNE;
    1.56 +      case TOK_GT:
    1.57 +        return OP_JG;
    1.58 +      case TOK_GE:
    1.59 +        return OP_JGE;
    1.60 +      case TOK_LT:
    1.61 +        return OP_JL;
    1.62 +      case TOK_LE:
    1.63 +        return OP_JLE;
    1.64 +    }
    1.65 +    assert(false);
    1.66 +    return OP_NOP;
    1.67 +}
    1.68 +
    1.69 +static inline Opcode
    1.70 +TokenToOpcode(TokenKind kind)
    1.71 +{
    1.72 +    switch (kind) {
    1.73 +      case TOK_PLUS:
    1.74 +        return OP_ADD;
    1.75 +      case TOK_MINUS:
    1.76 +        return OP_SUB;
    1.77 +      case TOK_STAR:
    1.78 +        return OP_MUL;
    1.79 +      case TOK_SLASH:
    1.80 +        return OP_DIV;
    1.81 +    }
    1.82 +    assert(false);
    1.83 +    return OP_NOP;
    1.84 +}
    1.85 +
    1.86 +void
    1.87 +BytecodeCompiler::visit(NameProxy *name)
    1.88 +{
    1.89 +    Variable *var = name->binding()->toVariable();
    1.90 +
    1.91 +    if (var->location() == Variable::STACK) {
    1.92 +        __ getlocal(var->slot());
    1.93 +    } else {
    1.94 +        assert(var->location() == Variable::PARAMETER);
    1.95 +        __ getarg(var->slot());
    1.96 +    }
    1.97 +}
    1.98 +
    1.99 +void
   1.100 +BytecodeCompiler::visit(ExpressionStatement *node)
   1.101 +{
   1.102 +    // Expressions leave their value on the top of the stack, so we make sure
   1.103 +    // to balance the stack if they're used as a statement.
   1.104 +    node->expression()->accept(this);
   1.105 +    __ pop();
   1.106 +}
   1.107 +
   1.108 +void
   1.109 +BytecodeCompiler::visit(Assignment *node)
   1.110 +{
   1.111 +    if (node->lvalue()->isNameProxy()) {
   1.112 +        NameProxy *proxy = node->lvalue()->toNameProxy();
   1.113 +        Variable *var = proxy->binding()->toVariable();
   1.114 +
   1.115 +        node->expression()->accept(this);
   1.116 +        if (var->location() == Variable::STACK) {
   1.117 +            __ setlocal(var->slot());
   1.118 +        } else {
   1.119 +            assert(var->location() == Variable::PARAMETER);
   1.120 +            __ setarg(var->slot());
   1.121 +        }
   1.122 +    } else if (node->lvalue()->isIndexExpression()) {
   1.123 +        IndexExpression *index = node->lvalue()->toIndexExpression();
   1.124 +
   1.125 +        index->left()->accept(this);
   1.126 +        index->right()->accept(this);
   1.127 +        __ bounds_sta();
   1.128 +        node->expression()->accept(this);
   1.129 +        __ st_sta_i();
   1.130 +    }
   1.131 +}
   1.132 +
   1.133 +void
   1.134 +BytecodeCompiler::visit(BinaryExpression *node)
   1.135 +{
   1.136 +    node->left()->accept(this);
   1.137 +    node->right()->accept(this);
   1.138 +
   1.139 +    Opcode op = TokenToOpcode(node->token());
   1.140 +    __ binary(op);
   1.141 +}
   1.142 +
   1.143 +void
   1.144 +BytecodeCompiler::visit(IndexExpression *node)
   1.145 +{
   1.146 +    node->left()->accept(this);
   1.147 +    node->right()->accept(this);
   1.148 +    __ bounds_sta();
   1.149 +
   1.150 +    if (node->type()->isArray())
   1.151 +        __ ld_sta_p();
   1.152 +    else
   1.153 +        __ ld_sta_i();
   1.154 +}
   1.155 +
   1.156 +void
   1.157 +BytecodeCompiler::visit(ReturnStatement *node)
   1.158 +{
   1.159 +    if (node->expression())
   1.160 +        node->expression()->accept(this);
   1.161 +    else
   1.162 +        __ int_(0);
   1.163 +
   1.164 +    __ return_();
   1.165 +}
   1.166 +
   1.167 +void
   1.168 +BytecodeCompiler::visitForTest(Expression *expression, Label *label, bool onTrue)
   1.169 +{
   1.170 +    TokenKind token = ToCompare(expression);
   1.171 +    if (token == TOK_EOF) {
   1.172 +        expression->accept(this);
   1.173 +        if (onTrue)
   1.174 +            __ j(OP_JT, label);
   1.175 +        else
   1.176 +            __ j(OP_JF, label);
   1.177 +        return;
   1.178 +    }
   1.179 +
   1.180 +    Opcode op = CompareTokenToJump(token);
   1.181 +    if (!onTrue)
   1.182 +        op = Invert(op);
   1.183 +
   1.184 +    assert(expression->isBinaryExpression());
   1.185 +    BinaryExpression *binary = expression->toBinaryExpression();
   1.186 +    binary->left()->accept(this);
   1.187 +    binary->right()->accept(this);
   1.188 +    __ j(op, label);
   1.189 +}
   1.190 +
   1.191 +void
   1.192 +BytecodeCompiler::visit(ForStatement *node)
   1.193 +{
   1.194 +    if (node->declaration())
   1.195 +        node->declaration()->accept(this);
   1.196 +
   1.197 +    Label header, test;
   1.198 +    if (node->condition())
   1.199 +        __ jump(&test);
   1.200 +
   1.201 +    __ bind(&header);
   1.202 +    node->body()->accept(this);
   1.203 +
   1.204 +    if (node->update())
   1.205 +        node->update()->accept(this);
   1.206 +
   1.207 +    if (node->condition()) {
   1.208 +        __ bind(&test);
   1.209 +        visitForTest(node->condition(), &header, true);
   1.210 +    } else {
   1.211 +        __ jump(&header);
   1.212 +    }
   1.213 +
   1.214 +    assert(__ stackDepth() == 0);
   1.215 +}
   1.216 +
   1.217 +void
   1.218 +BytecodeCompiler::visit(BlockStatement *node)
   1.219 +{
   1.220 +    for (size_t i = 0; i < node->statements()->length(); i++) {
   1.221 +        Statement *statement = node->statements()->at(i);
   1.222 +        statement->accept(this);
   1.223 +        assert(__ stackDepth() == 0);
   1.224 +    }
   1.225 +}
   1.226 +
   1.227 +void
   1.228 +BytecodeCompiler::visit(IntegerLiteralExpression *node)
   1.229 +{
   1.230 +    __ int_(node->value());
   1.231 +}
   1.232 +
   1.233 +void
   1.234 +BytecodeCompiler::visit(VariableDeclaration *node)
   1.235 +{
   1.236 +    Variable *var = node->variable();
   1.237 +    assert(var->location() == Variable::STACK);
   1.238 +    
   1.239 +    Type *type = var->type();
   1.240 +    if (type->isArray()) {
   1.241 +        bool isConstant = true;
   1.242 +        for (Type *child = type; child->isArray(); child = child->contained()) {
   1.243 +            if (child->elements() == Type::UNKNOWN_SIZE) {
   1.244 +                isConstant = false;
   1.245 +                break;
   1.246 +            }
   1.247 +        }
   1.248 +
   1.249 +        if (!isConstant) {
   1.250 +            for (size_t i = 0; i < node->postDimensions()->size(); i++) {
   1.251 +                Expression *expr = node->postDimensions()->at(i);
   1.252 +                expr->accept(this);
   1.253 +            }
   1.254 +        }
   1.255 +
   1.256 +        __ stackarray(type);
   1.257 +    } else {
   1.258 +        if (node->initialization()) {
   1.259 +            node->initialization()->accept(this);
   1.260 +        } else {
   1.261 +            if (!node->postDimensions())
   1.262 +                __ int_(0);
   1.263 +        }
   1.264 +    }
   1.265 +    __ setlocal(var->slot());
   1.266 +    __ pop();
   1.267 +
   1.268 +    locals_[var->slot()] = var->type();
   1.269 +}
   1.270 +
   1.271 +void
   1.272 +BytecodeCompiler::visit(CallExpression *node)
   1.273 +{
   1.274 +    NameProxy *fun = node->callee()->toNameProxy();
   1.275 +
   1.276 +    for (size_t i = 0; i < node->arguments()->size(); i++) {
   1.277 +        Expression *arg = node->arguments()->at(i);
   1.278 +        arg->accept(this);
   1.279 +    }
   1.280 +
   1.281 +    __ callglobal(node->arguments()->size(), 0);
   1.282 +}
   1.283 +
   1.284 +void
   1.285 +BytecodeCompiler::visit(IfStatement *node)
   1.286 +{
   1.287 +    if (!node->ifFalse()) {
   1.288 +        Label fail;
   1.289 +        visitForTest(node->condition(), &fail, false);
   1.290 +        node->ifTrue()->accept(this);
   1.291 +        __ bind(&fail);
   1.292 +    } else {
   1.293 +        Label fail, join;
   1.294 +        visitForTest(node->condition(), &fail, false);
   1.295 +        node->ifTrue()->accept(this);
   1.296 +        __ jump(&join);
   1.297 +        __ bind(&fail);
   1.298 +        node->ifFalse()->accept(this);
   1.299 +        __ bind(&join);
   1.300 +    }
   1.301 +}
   1.302 +
   1.303 +void
   1.304 +BytecodeCompiler::visit(FunctionStatement *node)
   1.305 +{
   1.306 +    BytecodeCompiler child(tree_);
   1.307 +    Code *code = child.compileFunction(module_, node);
   1.308 +    
   1.309 +    assert(!module_->getFunction(node->fun()->slot()));
   1.310 +    module_->setFunction(node->fun()->slot(), code);
   1.311 +}
   1.312 +
   1.313 +Code *
   1.314 +BytecodeCompiler::compileFunction(Module *module, FunctionStatement *node)
   1.315 +{
   1.316 +    locals_ = new Type *[node->scope()->maxContainedLocals()];
   1.317 +    memset(locals_, 0, sizeof(Type *) * node->scope()->maxContainedLocals());
   1.318 +
   1.319 +    node->body()->accept(this);
   1.320 +
   1.321 +    __ stop();
   1.322 +
   1.323 +    if (__ oom())
   1.324 +        return false;
   1.325 +
   1.326 +    bytecode *start = (bytecode *)malloc(__ length() * sizeof(bytecode));
   1.327 +    memcpy(start, __ buffer(), __ length());
   1.328 +
   1.329 +    unsigned nargs = node->scope()->numArguments();
   1.330 +    Type **args = new Type *[nargs];
   1.331 +    for (size_t i = 0; i < node->scope()->numArguments(); i++)
   1.332 +        args[i] = node->scope()->getArgument(i)->type();
   1.333 +
   1.334 +    for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
   1.335 +        assert(locals_[i]);
   1.336 +
   1.337 +    Code *code = new Code(module,
   1.338 +                          start,
   1.339 +                          __ length(),
   1.340 +                          args,
   1.341 +                          nargs,
   1.342 +                          locals_,
   1.343 +                          node->scope()->maxContainedLocals(),
   1.344 +                          __ maxStackDepth());
   1.345 +
   1.346 +    return code;
   1.347 +}
   1.348 +
   1.349 +Module *
   1.350 +BytecodeCompiler::compile()
   1.351 +{
   1.352 +    Code **functions = new Code *[tree_->scope()->numFunctions()];
   1.353 +    memset(functions, 0, sizeof(Code *) * tree_->scope()->numFunctions());
   1.354 +
   1.355 +    module_ = new Module(functions, tree_->scope()->numFunctions());
   1.356 +
   1.357 +    for (size_t i = 0; i < tree_->statements()->length(); i++) {
   1.358 +        Statement *statement = tree_->statements()->at(i);
   1.359 +        statement->accept(this);
   1.360 +    }
   1.361 +
   1.362 +#ifndef NDEBUG
   1.363 +    for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
   1.364 +        assert(functions[i]);
   1.365 +#endif
   1.366 +
   1.367 +    return module_;
   1.368 +}