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