src/compiler/HIR.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 18 15:24:30 2012 -0800 (2012-11-18)
changeset 215 b8f650a441a5
parent 212 443d24cfdf2d
child 217 c22e983b3b6e
permissions -rw-r--r--
Get load-store assign ops 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         return OP_ADD;
   192       case TOK_MINUS:
   193       case TOK_ASSIGN_SUB:
   194         return OP_SUB;
   195       case TOK_STAR:
   196       case TOK_ASSIGN_MUL:
   197         return OP_MUL;
   198       case TOK_SLASH:
   199       case TOK_ASSIGN_DIV:
   200         return OP_DIV;
   201       case TOK_PERCENT:
   202       case TOK_ASSIGN_MOD:
   203         return OP_MOD;
   204       case TOK_SHR:
   205       case TOK_ASSIGN_SHR:
   206         return OP_SHR;
   207       case TOK_USHR:
   208       case TOK_ASSIGN_USHR:
   209         return OP_USHR;
   210       case TOK_SHL:
   211       case TOK_ASSIGN_SHL:
   212         return OP_SHL;
   213       case TOK_BITAND:
   214       case TOK_ASSIGN_BITAND:
   215         return OP_BITAND;
   216       case TOK_BITOR:
   217       case TOK_ASSIGN_BITOR:
   218         return OP_BITOR;
   219       case TOK_GT:
   220           return OP_GT;
   221       case TOK_GE:
   222           return OP_GE;
   223       case TOK_LT:
   224           return OP_LT;
   225       case TOK_LE:
   226           return OP_LE;
   227       case TOK_EQUALS:
   228           return OP_EQ;
   229       case TOK_NOTEQUALS:
   230           return OP_NE;
   231       default:
   232         assert(kind == TOK_BITXOR);
   233         return OP_BITXOR;
   234     }
   235 }
   236 
   237 void
   238 HIRTranslator::visitStore(HStore *store)
   239 {
   240     store->lval()->bind(this, emitter_);
   241     if (store->kind() == TOK_ASSIGN) {
   242         store->rval()->accept(this);
   243     } else {
   244         // Advanced case: dup the ref, load, op, store.
   245         store->lval()->hold(emitter_);
   246         store->lval()->load(emitter_);
   247         store->rval()->accept(this);
   248         __ binary(TokenToOpcode(store->kind()));
   249     }
   250     store->lval()->store(emitter_);
   251 }
   252 
   253 void
   254 HIRTranslator::visitBinary(HBinary *binary)
   255 {
   256     binary->left()->accept(this);
   257     binary->right()->accept(this);
   258 
   259     // We define three sets of math operators:
   260     //
   261     //  (1) ADD, SUB, MUL, DIV, MOD, which take two equal types and produce
   262     //      the same type.
   263     //  (2) LT, LE, GE, GT, EQ, NE, which take two equal types and produce
   264     //      a boolean.
   265     //  (3) SHL, SR, USHR, BITAND, BITOR, BITXOR, BITNOT, which take two
   266     //      equal integer types and return that integer type.
   267     //
   268     Opcode op = TokenToOpcode(binary->token());
   269 
   270     if (op >= OP_ADD && op <= OP_NE) {
   271         if (binary->type()->isFloat())
   272             op = Opcode(int(op) + int(OP_ADD_F - OP_ADD));
   273     } else {
   274         assert(binary->type()->isInt32());
   275     }
   276 
   277     __ binary(op);
   278 }
   279 
   280 void
   281 HIRTranslator::visitConvert(HConvert *convert)
   282 {
   283     convert->in()->accept(this);
   284     __ unary(convert->opcode());
   285 }
   286 
   287 void
   288 ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
   289 {
   290     HIRTranslator translator(zone, emitter);
   291     translator.translate(hir);
   292 }