src/compiler/HIR.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 18 15:50:41 2012 -0800 (2012-11-18)
changeset 217 c22e983b3b6e
parent 215 b8f650a441a5
child 218 ccb089827f87
permissions -rw-r--r--
Get preinc working again.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     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)
    10  * any later version.
    11  * 
    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.
    15  *
    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/.
    18  */
    19 #include "HIR.h"
    20 #include "BytecodeEmitter.h"
    21 #include "../Heap-inl.h"
    22 #include "../Handles-inl.h"
    23 
    24 using namespace ke;
    25 
    26 class HIRTranslator : public HIRVisitor
    27 {
    28   public:
    29     HIRTranslator(Zone *zone, BytecodeEmitter &emitter)
    30       : zone_(zone),
    31         emitter_(emitter)
    32     {
    33     }
    34 
    35     void translate(HIR *hir) {
    36         hir->accept(this);
    37     }
    38 
    39     void visitFloat(HFloat *hir);
    40     void visitInteger(HInteger *hir);
    41     void visitCall(HCall *call);
    42     void visitStore(HStore *store);
    43     void visitBinary(HBinary *binary);
    44     void visitLocal(HLocal *local);
    45     void visitGlobal(HGlobal *global);
    46     void visitConvert(HConvert *convert);
    47     void visitIndex(HIndex *index);
    48 
    49   private:
    50     Zone *zone_;
    51     BytecodeEmitter &emitter_;
    52 };
    53 
    54 #define __ emitter_.
    55 
    56 void
    57 HIRTranslator::visitFloat(HFloat *hir)
    58 {
    59     __ float_(hir->value());
    60 }
    61 
    62 void
    63 HIRTranslator::visitInteger(HInteger *hir)
    64 {
    65     __ int_(hir->value());
    66 }
    67 
    68 void
    69 HIRTranslator::visitCall(HCall *call)
    70 {
    71     Local<FunctionType> fun(zone_, FunctionType::cast(call->callee()->type()));
    72     
    73     assert(call->args()->length() == fun->parameters()->length());
    74 
    75     unsigned argc = call->args()->length();
    76 
    77     for (size_t i = call->args()->length() - 1; i < call->args()->length(); i--) {
    78         HIR *hir = call->args()->at(i);
    79         hir->accept(this);
    80     }
    81 
    82     call->callee()->accept(this);
    83     __ call(fun, argc);
    84 }
    85 
    86 void
    87 HGlobal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
    88 {
    89 }
    90 
    91 void
    92 HGlobal::hold(BytecodeEmitter &emitter_)
    93 {
    94 }
    95 
    96 void
    97 HGlobal::store(BytecodeEmitter &emitter_)
    98 {
    99     __ setglobal(sym_);
   100 }
   101 
   102 void
   103 HGlobal::load(BytecodeEmitter &emitter_)
   104 {
   105     __ getglobal(sym_);
   106 }
   107 
   108 void
   109 HLocal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
   110 {
   111     if (sym_->type()->isReference())
   112         __ getlocal(sym_);
   113 }
   114 
   115 void
   116 HLocal::hold(BytecodeEmitter &emitter_)
   117 {
   118     if (sym_->type()->isReference())
   119         __ dup();
   120 }
   121 
   122 void
   123 HLocal::store(BytecodeEmitter &emitter_)
   124 {
   125     if (sym_->type()->isReference())
   126         __ setref(sym_->type()->contained_ref());
   127     else
   128         __ setlocal(sym_);
   129 }
   130 
   131 void
   132 HLocal::load(BytecodeEmitter &emitter_)
   133 {
   134     if (sym_->type()->isReference())
   135         __ getref(sym_->type());
   136     else
   137         __ getlocal(sym_);
   138 }
   139 
   140 void
   141 HIndex::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
   142 {
   143     left_->accept(visitor);
   144     right_->accept(visitor);
   145 }
   146 
   147 void
   148 HIndex::hold(BytecodeEmitter &emitter_)
   149 {
   150     __ dup2();
   151 }
   152 
   153 void
   154 HIndex::store(BytecodeEmitter &emitter_)
   155 {
   156     __ setelem(type());
   157 }
   158 
   159 void
   160 HIndex::load(BytecodeEmitter &emitter_)
   161 {
   162     __ getelem(type());
   163 }
   164 
   165 void
   166 HIRTranslator::visitLocal(HLocal *local)
   167 {
   168     local->bind(this, emitter_);
   169     local->load(emitter_);
   170 }
   171 
   172 void
   173 HIRTranslator::visitIndex(HIndex *index)
   174 {
   175     index->bind(this, emitter_);
   176     index->load(emitter_);
   177 }
   178 
   179 void
   180 HIRTranslator::visitGlobal(HGlobal *global)
   181 {
   182     __ getglobal(global->sym());
   183 }
   184 
   185 static inline Opcode
   186 TokenToOpcode(TokenKind kind)
   187 {
   188     switch (kind) {
   189       case TOK_PLUS:
   190       case TOK_ASSIGN_ADD:
   191       case TOK_INCREMENT:
   192         return OP_ADD;
   193       case TOK_MINUS:
   194       case TOK_ASSIGN_SUB:
   195       case TOK_DECREMENT:
   196         return OP_SUB;
   197       case TOK_STAR:
   198       case TOK_ASSIGN_MUL:
   199         return OP_MUL;
   200       case TOK_SLASH:
   201       case TOK_ASSIGN_DIV:
   202         return OP_DIV;
   203       case TOK_PERCENT:
   204       case TOK_ASSIGN_MOD:
   205         return OP_MOD;
   206       case TOK_SHR:
   207       case TOK_ASSIGN_SHR:
   208         return OP_SHR;
   209       case TOK_USHR:
   210       case TOK_ASSIGN_USHR:
   211         return OP_USHR;
   212       case TOK_SHL:
   213       case TOK_ASSIGN_SHL:
   214         return OP_SHL;
   215       case TOK_BITAND:
   216       case TOK_ASSIGN_BITAND:
   217         return OP_BITAND;
   218       case TOK_BITOR:
   219       case TOK_ASSIGN_BITOR:
   220         return OP_BITOR;
   221       case TOK_GT:
   222           return OP_GT;
   223       case TOK_GE:
   224           return OP_GE;
   225       case TOK_LT:
   226           return OP_LT;
   227       case TOK_LE:
   228           return OP_LE;
   229       case TOK_EQUALS:
   230           return OP_EQ;
   231       case TOK_NOTEQUALS:
   232           return OP_NE;
   233       default:
   234         assert(kind == TOK_BITXOR);
   235         return OP_BITXOR;
   236     }
   237 }
   238 
   239 void
   240 HIRTranslator::visitStore(HStore *store)
   241 {
   242     store->lval()->bind(this, emitter_);
   243     if (store->kind() == TOK_ASSIGN) {
   244         store->rval()->accept(this);
   245     } else {
   246         // Advanced case: dup the ref, load, op, store.
   247         store->lval()->hold(emitter_);
   248         store->lval()->load(emitter_);
   249         store->rval()->accept(this);
   250         __ binary(TokenToOpcode(store->kind()));
   251     }
   252     store->lval()->store(emitter_);
   253 }
   254 
   255 void
   256 HIRTranslator::visitBinary(HBinary *binary)
   257 {
   258     binary->left()->accept(this);
   259     binary->right()->accept(this);
   260 
   261     // We define three sets of math operators:
   262     //
   263     //  (1) ADD, SUB, MUL, DIV, MOD, which take two equal types and produce
   264     //      the same type.
   265     //  (2) LT, LE, GE, GT, EQ, NE, which take two equal types and produce
   266     //      a boolean.
   267     //  (3) SHL, SR, USHR, BITAND, BITOR, BITXOR, BITNOT, which take two
   268     //      equal integer types and return that integer type.
   269     //
   270     Opcode op = TokenToOpcode(binary->token());
   271 
   272     if (op >= OP_ADD && op <= OP_NE) {
   273         if (binary->type()->isFloat())
   274             op = Opcode(int(op) + int(OP_ADD_F - OP_ADD));
   275     } else {
   276         assert(binary->type()->isInt32());
   277     }
   278 
   279     __ binary(op);
   280 }
   281 
   282 void
   283 HIRTranslator::visitConvert(HConvert *convert)
   284 {
   285     convert->in()->accept(this);
   286     __ unary(convert->opcode());
   287 }
   288 
   289 void
   290 ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
   291 {
   292     HIRTranslator translator(zone, emitter);
   293     translator.translate(hir);
   294 }