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