jitcraft/BytecodeCompiler.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jun 25 02:57:28 2012 -0700 (2012-06-25)
changeset 0 c455ebb9a5dc
child 1 27f12e2fc369
permissions -rw-r--r--
Initial import of prototype.
     1 /*
     2  * Copyright (C) 2012 David Anderson
     3  *
     4  * This file is part of JITCraft.
     5  *
     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)
     9  * any later version.
    10  * 
    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.
    14  *
    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/.
    17  */
    18 #include "BytecodeCompiler.h"
    19 #include "Scopes.h"
    20 #include "Modules.h"
    21 #include "Types.h"
    22 
    23 using namespace jc;
    24 
    25 typedef BytecodeEmitter::Label Label;
    26 
    27 #define __ emitter_.
    28 
    29 BytecodeCompiler::BytecodeCompiler(ParseTree *tree)
    30   : tree_(tree)
    31 {
    32 }
    33 
    34 static inline TokenKind
    35 ToCompare(Expression *expr)
    36 {
    37     if (expr->isBinaryExpression()) {
    38         BinaryExpression *b = expr->toBinaryExpression();
    39         if (b->token() >= TOK_EQUALS && b->token() <= TOK_GE)
    40             return b->token();
    41     }
    42     return TOK_EOF;
    43 }
    44 
    45 static inline Opcode
    46 CompareTokenToJump(TokenKind kind)
    47 {
    48     switch (kind) {
    49       case TOK_EQUALS:
    50         return OP_JEQ;
    51       case TOK_NOTEQUALS:
    52         return OP_JNE;
    53       case TOK_GT:
    54         return OP_JG;
    55       case TOK_GE:
    56         return OP_JGE;
    57       case TOK_LT:
    58         return OP_JL;
    59       case TOK_LE:
    60         return OP_JLE;
    61     }
    62     assert(false);
    63     return OP_NOP;
    64 }
    65 
    66 static inline Opcode
    67 TokenToOpcode(TokenKind kind)
    68 {
    69     switch (kind) {
    70       case TOK_PLUS:
    71         return OP_ADD;
    72       case TOK_MINUS:
    73         return OP_SUB;
    74       case TOK_STAR:
    75         return OP_MUL;
    76       case TOK_SLASH:
    77         return OP_DIV;
    78     }
    79     assert(false);
    80     return OP_NOP;
    81 }
    82 
    83 void
    84 BytecodeCompiler::visit(NameProxy *name)
    85 {
    86     Variable *var = name->binding()->toVariable();
    87 
    88     if (var->location() == Variable::STACK) {
    89         __ getlocal(var->slot());
    90     } else {
    91         assert(var->location() == Variable::PARAMETER);
    92         __ getarg(var->slot());
    93     }
    94 }
    95 
    96 void
    97 BytecodeCompiler::visit(ExpressionStatement *node)
    98 {
    99     // Expressions leave their value on the top of the stack, so we make sure
   100     // to balance the stack if they're used as a statement.
   101     node->expression()->accept(this);
   102     __ pop();
   103 }
   104 
   105 void
   106 BytecodeCompiler::visit(Assignment *node)
   107 {
   108     if (node->lvalue()->isNameProxy()) {
   109         NameProxy *proxy = node->lvalue()->toNameProxy();
   110         Variable *var = proxy->binding()->toVariable();
   111 
   112         node->expression()->accept(this);
   113         if (var->location() == Variable::STACK) {
   114             __ setlocal(var->slot());
   115         } else {
   116             assert(var->location() == Variable::PARAMETER);
   117             __ setarg(var->slot());
   118         }
   119     } else if (node->lvalue()->isIndexExpression()) {
   120         IndexExpression *index = node->lvalue()->toIndexExpression();
   121 
   122         index->left()->accept(this);
   123         index->right()->accept(this);
   124         __ bounds_sta();
   125         node->expression()->accept(this);
   126         __ st_sta_i();
   127     }
   128 }
   129 
   130 void
   131 BytecodeCompiler::visit(BinaryExpression *node)
   132 {
   133     node->left()->accept(this);
   134     node->right()->accept(this);
   135 
   136     Opcode op = TokenToOpcode(node->token());
   137     __ binary(op);
   138 }
   139 
   140 void
   141 BytecodeCompiler::visit(IndexExpression *node)
   142 {
   143     node->left()->accept(this);
   144     node->right()->accept(this);
   145     __ bounds_sta();
   146 
   147     if (node->type()->isArray())
   148         __ ld_sta_p();
   149     else
   150         __ ld_sta_i();
   151 }
   152 
   153 void
   154 BytecodeCompiler::visit(ReturnStatement *node)
   155 {
   156     if (node->expression())
   157         node->expression()->accept(this);
   158     else
   159         __ int_(0);
   160 
   161     __ return_();
   162 }
   163 
   164 void
   165 BytecodeCompiler::visitForTest(Expression *expression, Label *label, bool onTrue)
   166 {
   167     TokenKind token = ToCompare(expression);
   168     if (token == TOK_EOF) {
   169         expression->accept(this);
   170         if (onTrue)
   171             __ j(OP_JT, label);
   172         else
   173             __ j(OP_JF, label);
   174         return;
   175     }
   176 
   177     Opcode op = CompareTokenToJump(token);
   178     if (!onTrue)
   179         op = Invert(op);
   180 
   181     assert(expression->isBinaryExpression());
   182     BinaryExpression *binary = expression->toBinaryExpression();
   183     binary->left()->accept(this);
   184     binary->right()->accept(this);
   185     __ j(op, label);
   186 }
   187 
   188 void
   189 BytecodeCompiler::visit(ForStatement *node)
   190 {
   191     if (node->declaration())
   192         node->declaration()->accept(this);
   193 
   194     Label header, test;
   195     if (node->condition())
   196         __ jump(&test);
   197 
   198     __ bind(&header);
   199     node->body()->accept(this);
   200 
   201     if (node->update())
   202         node->update()->accept(this);
   203 
   204     if (node->condition()) {
   205         __ bind(&test);
   206         visitForTest(node->condition(), &header, true);
   207     } else {
   208         __ jump(&header);
   209     }
   210 
   211     assert(__ stackDepth() == 0);
   212 }
   213 
   214 void
   215 BytecodeCompiler::visit(BlockStatement *node)
   216 {
   217     for (size_t i = 0; i < node->statements()->length(); i++) {
   218         Statement *statement = node->statements()->at(i);
   219         statement->accept(this);
   220         assert(__ stackDepth() == 0);
   221     }
   222 }
   223 
   224 void
   225 BytecodeCompiler::visit(IntegerLiteralExpression *node)
   226 {
   227     __ int_(node->value());
   228 }
   229 
   230 void
   231 BytecodeCompiler::visit(VariableDeclaration *node)
   232 {
   233     Variable *var = node->variable();
   234     assert(var->location() == Variable::STACK);
   235     
   236     Type *type = var->type();
   237     if (type->isArray()) {
   238         bool isConstant = true;
   239         for (Type *child = type; child->isArray(); child = child->contained()) {
   240             if (child->elements() == Type::UNKNOWN_SIZE) {
   241                 isConstant = false;
   242                 break;
   243             }
   244         }
   245 
   246         if (!isConstant) {
   247             for (size_t i = 0; i < node->postDimensions()->size(); i++) {
   248                 Expression *expr = node->postDimensions()->at(i);
   249                 expr->accept(this);
   250             }
   251         }
   252 
   253         __ stackarray(type);
   254     } else {
   255         if (node->initialization()) {
   256             node->initialization()->accept(this);
   257         } else {
   258             if (!node->postDimensions())
   259                 __ int_(0);
   260         }
   261     }
   262     __ setlocal(var->slot());
   263     __ pop();
   264 
   265     locals_[var->slot()] = var->type();
   266 }
   267 
   268 void
   269 BytecodeCompiler::visit(CallExpression *node)
   270 {
   271     NameProxy *fun = node->callee()->toNameProxy();
   272 
   273     for (size_t i = 0; i < node->arguments()->size(); i++) {
   274         Expression *arg = node->arguments()->at(i);
   275         arg->accept(this);
   276     }
   277 
   278     __ callglobal(node->arguments()->size(), 0);
   279 }
   280 
   281 void
   282 BytecodeCompiler::visit(IfStatement *node)
   283 {
   284     if (!node->ifFalse()) {
   285         Label fail;
   286         visitForTest(node->condition(), &fail, false);
   287         node->ifTrue()->accept(this);
   288         __ bind(&fail);
   289     } else {
   290         Label fail, join;
   291         visitForTest(node->condition(), &fail, false);
   292         node->ifTrue()->accept(this);
   293         __ jump(&join);
   294         __ bind(&fail);
   295         node->ifFalse()->accept(this);
   296         __ bind(&join);
   297     }
   298 }
   299 
   300 void
   301 BytecodeCompiler::visit(FunctionStatement *node)
   302 {
   303     BytecodeCompiler child(tree_);
   304     Code *code = child.compileFunction(module_, node);
   305     
   306     assert(!module_->getFunction(node->fun()->slot()));
   307     module_->setFunction(node->fun()->slot(), code);
   308 }
   309 
   310 Code *
   311 BytecodeCompiler::compileFunction(Module *module, FunctionStatement *node)
   312 {
   313     locals_ = new Type *[node->scope()->maxContainedLocals()];
   314     memset(locals_, 0, sizeof(Type *) * node->scope()->maxContainedLocals());
   315 
   316     node->body()->accept(this);
   317 
   318     __ stop();
   319 
   320     if (__ oom())
   321         return false;
   322 
   323     bytecode *start = (bytecode *)malloc(__ length() * sizeof(bytecode));
   324     memcpy(start, __ buffer(), __ length());
   325 
   326     unsigned nargs = node->scope()->numArguments();
   327     Type **args = new Type *[nargs];
   328     for (size_t i = 0; i < node->scope()->numArguments(); i++)
   329         args[i] = node->scope()->getArgument(i)->type();
   330 
   331     for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
   332         assert(locals_[i]);
   333 
   334     Code *code = new Code(module,
   335                           start,
   336                           __ length(),
   337                           args,
   338                           nargs,
   339                           locals_,
   340                           node->scope()->maxContainedLocals(),
   341                           __ maxStackDepth());
   342 
   343     return code;
   344 }
   345 
   346 Module *
   347 BytecodeCompiler::compile()
   348 {
   349     Code **functions = new Code *[tree_->scope()->numFunctions()];
   350     memset(functions, 0, sizeof(Code *) * tree_->scope()->numFunctions());
   351 
   352     module_ = new Module(functions, tree_->scope()->numFunctions());
   353 
   354     for (size_t i = 0; i < tree_->statements()->length(); i++) {
   355         Statement *statement = tree_->statements()->at(i);
   356         statement->accept(this);
   357     }
   358 
   359 #ifndef NDEBUG
   360     for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
   361         assert(functions[i]);
   362 #endif
   363 
   364     return module_;
   365 }