src/compiler/HIR.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 18 14:53:23 2012 -0800 (2012-11-18)
changeset 212 443d24cfdf2d
parent 209 5cbec15fadfe
child 215 b8f650a441a5
permissions -rw-r--r--
Added array support back.
     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::store(BytecodeEmitter &emitter_)
    93 {
    94     __ setglobal(sym_);
    95 }
    96 
    97 void
    98 HGlobal::load(BytecodeEmitter &emitter_)
    99 {
   100     __ getglobal(sym_);
   101 }
   102 
   103 void
   104 HLocal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
   105 {
   106     if (sym_->type()->isReference())
   107         __ getlocal(sym_);
   108 }
   109 
   110 void
   111 HLocal::store(BytecodeEmitter &emitter_)
   112 {
   113     if (sym_->type()->isReference())
   114         __ setref(sym_->type()->contained_ref());
   115     else
   116         __ setlocal(sym_);
   117 }
   118 
   119 void
   120 HLocal::load(BytecodeEmitter &emitter_)
   121 {
   122     if (sym_->type()->isReference())
   123         __ getref(sym_->type());
   124     else
   125         __ getlocal(sym_);
   126 }
   127 
   128 void
   129 HIndex::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
   130 {
   131     left_->accept(visitor);
   132     right_->accept(visitor);
   133 }
   134 
   135 void
   136 HIndex::store(BytecodeEmitter &emitter_)
   137 {
   138     __ setelem(type());
   139 }
   140 
   141 void
   142 HIndex::load(BytecodeEmitter &emitter_)
   143 {
   144     __ getelem(type());
   145 }
   146 
   147 void
   148 HIRTranslator::visitLocal(HLocal *local)
   149 {
   150     local->bind(this, emitter_);
   151     local->load(emitter_);
   152 }
   153 
   154 void
   155 HIRTranslator::visitIndex(HIndex *index)
   156 {
   157     index->bind(this, emitter_);
   158     index->load(emitter_);
   159 }
   160 
   161 void
   162 HIRTranslator::visitGlobal(HGlobal *global)
   163 {
   164     __ getglobal(global->sym());
   165 }
   166 
   167 void
   168 HIRTranslator::visitStore(HStore *store)
   169 {
   170     store->lval()->bind(this, emitter_);
   171     store->rval()->accept(this);
   172     store->lval()->store(emitter_);
   173 }
   174 
   175 static inline Opcode
   176 TokenToOpcode(TokenKind kind)
   177 {
   178     switch (kind) {
   179       case TOK_PLUS:
   180         return OP_ADD;
   181       case TOK_MINUS:
   182         return OP_SUB;
   183       case TOK_STAR:
   184         return OP_MUL;
   185       case TOK_SLASH:
   186         return OP_DIV;
   187       case TOK_PERCENT:
   188         return OP_MOD;
   189       case TOK_SHR:
   190         return OP_SHR;
   191       case TOK_USHR:
   192         return OP_USHR;
   193       case TOK_SHL:
   194         return OP_SHL;
   195       case TOK_BITAND:
   196         return OP_BITAND;
   197       case TOK_BITOR:
   198         return OP_BITOR;
   199       case TOK_GT:
   200           return OP_GT;
   201       case TOK_GE:
   202           return OP_GE;
   203       case TOK_LT:
   204           return OP_LT;
   205       case TOK_LE:
   206           return OP_LE;
   207       case TOK_EQUALS:
   208           return OP_EQ;
   209       case TOK_NOTEQUALS:
   210           return OP_NE;
   211       default:
   212         assert(kind == TOK_BITXOR);
   213         return OP_BITXOR;
   214     }
   215 }
   216 
   217 void
   218 HIRTranslator::visitBinary(HBinary *binary)
   219 {
   220     binary->left()->accept(this);
   221     binary->right()->accept(this);
   222 
   223     // We define three sets of math operators:
   224     //
   225     //  (1) ADD, SUB, MUL, DIV, MOD, which take two equal types and produce
   226     //      the same type.
   227     //  (2) LT, LE, GE, GT, EQ, NE, which take two equal types and produce
   228     //      a boolean.
   229     //  (3) SHL, SR, USHR, BITAND, BITOR, BITXOR, BITNOT, which take two
   230     //      equal integer types and return that integer type.
   231     //
   232     Opcode op = TokenToOpcode(binary->token());
   233 
   234     if (op >= OP_ADD && op <= OP_NE) {
   235         if (binary->type()->isFloat())
   236             op = Opcode(int(op) + int(OP_ADD_F - OP_ADD));
   237     } else {
   238         assert(binary->type()->isInt32());
   239     }
   240 
   241     __ binary(op);
   242 }
   243 
   244 void
   245 HIRTranslator::visitConvert(HConvert *convert)
   246 {
   247     convert->in()->accept(this);
   248     __ unary(convert->opcode());
   249 }
   250 
   251 void
   252 ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
   253 {
   254     HIRTranslator translator(zone, emitter);
   255     translator.translate(hir);
   256 }