src/compiler/HIR.cpp
author David Anderson <dvander@alliedmods.net>
Sat Nov 17 19:07:49 2012 -0800 (2012-11-17)
changeset 196 9904633b1dfc
parent 195 c1ba166f3fc4
child 209 5cbec15fadfe
permissions -rw-r--r--
Fix Linux build problems.
dvander@195
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@195
     2
 *
dvander@195
     3
 * Copyright (C) 2012 David Anderson
dvander@195
     4
 *
dvander@195
     5
 * This file is part of JITCraft.
dvander@195
     6
 *
dvander@195
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@195
     8
 * the terms of the GNU General Public License as published by the Free
dvander@195
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@195
    10
 * any later version.
dvander@195
    11
 * 
dvander@195
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@195
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@195
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@195
    15
 *
dvander@195
    16
 * You should have received a copy of the GNU General Public License along with
dvander@195
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@195
    18
 */
dvander@195
    19
#include "HIR.h"
dvander@195
    20
#include "BytecodeEmitter.h"
dvander@196
    21
#include "../Heap-inl.h"
dvander@196
    22
#include "../Handles-inl.h"
dvander@195
    23
dvander@195
    24
using namespace ke;
dvander@195
    25
dvander@195
    26
class HIRTranslator : public HIRVisitor
dvander@195
    27
{
dvander@195
    28
  public:
dvander@195
    29
    HIRTranslator(Zone *zone, BytecodeEmitter &emitter)
dvander@195
    30
      : zone_(zone),
dvander@195
    31
        emitter_(emitter)
dvander@195
    32
    {
dvander@195
    33
    }
dvander@195
    34
dvander@195
    35
    void translate(HIR *hir) {
dvander@195
    36
        hir->accept(this);
dvander@195
    37
    }
dvander@195
    38
dvander@195
    39
    void visitFloat(HFloat *hir);
dvander@195
    40
    void visitInteger(HInteger *hir);
dvander@195
    41
    void visitCall(HCall *call);
dvander@195
    42
    void visitStore(HStore *store);
dvander@195
    43
    void visitBinary(HBinary *binary);
dvander@195
    44
    void visitLocal(HLocal *local);
dvander@195
    45
    void visitGlobal(HGlobal *global);
dvander@195
    46
    void visitConvert(HConvert *convert);
dvander@195
    47
dvander@195
    48
  private:
dvander@195
    49
    Zone *zone_;
dvander@195
    50
    BytecodeEmitter &emitter_;
dvander@195
    51
};
dvander@195
    52
dvander@195
    53
#define __ emitter_.
dvander@195
    54
dvander@195
    55
void
dvander@195
    56
HIRTranslator::visitFloat(HFloat *hir)
dvander@195
    57
{
dvander@195
    58
    __ float_(hir->value());
dvander@195
    59
}
dvander@195
    60
dvander@195
    61
void
dvander@195
    62
HIRTranslator::visitInteger(HInteger *hir)
dvander@195
    63
{
dvander@195
    64
    __ int_(hir->value());
dvander@195
    65
}
dvander@195
    66
dvander@195
    67
void
dvander@195
    68
HIRTranslator::visitCall(HCall *call)
dvander@195
    69
{
dvander@195
    70
    Local<FunctionType> fun(zone_, FunctionType::cast(call->callee()->type()));
dvander@195
    71
    
dvander@195
    72
    assert(call->args()->length() == fun->parameters()->length());
dvander@195
    73
dvander@195
    74
    unsigned argc = call->args()->length();
dvander@195
    75
dvander@195
    76
    for (size_t i = call->args()->length() - 1; i < call->args()->length(); i--) {
dvander@195
    77
        HIR *hir = call->args()->at(i);
dvander@195
    78
        hir->accept(this);
dvander@195
    79
    }
dvander@195
    80
dvander@195
    81
    call->callee()->accept(this);
dvander@195
    82
    __ call(fun, argc);
dvander@195
    83
}
dvander@195
    84
dvander@195
    85
void
dvander@195
    86
HGlobal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
dvander@195
    87
{
dvander@195
    88
}
dvander@195
    89
dvander@195
    90
void
dvander@195
    91
HGlobal::store(BytecodeEmitter &emitter_)
dvander@195
    92
{
dvander@195
    93
    __ setglobal(sym_);
dvander@195
    94
}
dvander@195
    95
dvander@195
    96
void
dvander@195
    97
HGlobal::load(BytecodeEmitter &emitter_)
dvander@195
    98
{
dvander@195
    99
    __ getglobal(sym_);
dvander@195
   100
}
dvander@195
   101
dvander@195
   102
void
dvander@195
   103
HLocal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
dvander@195
   104
{
dvander@195
   105
    if (sym_->type()->isReference())
dvander@195
   106
        __ getlocal(sym_);
dvander@195
   107
}
dvander@195
   108
dvander@195
   109
void
dvander@195
   110
HLocal::store(BytecodeEmitter &emitter_)
dvander@195
   111
{
dvander@195
   112
    if (sym_->type()->isReference())
dvander@195
   113
        __ setref(sym_->type()->contained());
dvander@195
   114
    else
dvander@195
   115
        __ setlocal(sym_);
dvander@195
   116
}
dvander@195
   117
dvander@195
   118
void
dvander@195
   119
HLocal::load(BytecodeEmitter &emitter_)
dvander@195
   120
{
dvander@195
   121
    if (sym_->type()->isReference())
dvander@195
   122
        __ getref(sym_->type());
dvander@195
   123
    else
dvander@195
   124
        __ getlocal(sym_);
dvander@195
   125
}
dvander@195
   126
dvander@195
   127
void
dvander@195
   128
HIndex::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
dvander@195
   129
{
dvander@195
   130
    left_->accept(visitor);
dvander@195
   131
    right_->accept(visitor);
dvander@195
   132
}
dvander@195
   133
dvander@195
   134
void
dvander@195
   135
HIndex::store(BytecodeEmitter &emitter_)
dvander@195
   136
{
dvander@195
   137
    __ setelem(type());
dvander@195
   138
}
dvander@195
   139
dvander@195
   140
void
dvander@195
   141
HIndex::load(BytecodeEmitter &emitter_)
dvander@195
   142
{
dvander@195
   143
    __ getelem(type());
dvander@195
   144
}
dvander@195
   145
dvander@195
   146
void
dvander@195
   147
HIRTranslator::visitLocal(HLocal *local)
dvander@195
   148
{
dvander@195
   149
    local->bind(this, emitter_);
dvander@195
   150
    local->load(emitter_);
dvander@195
   151
}
dvander@195
   152
dvander@195
   153
void
dvander@195
   154
HIRTranslator::visitGlobal(HGlobal *global)
dvander@195
   155
{
dvander@195
   156
    __ getglobal(global->sym());
dvander@195
   157
}
dvander@195
   158
dvander@195
   159
void
dvander@195
   160
HIRTranslator::visitStore(HStore *store)
dvander@195
   161
{
dvander@195
   162
    store->lval()->bind(this, emitter_);
dvander@195
   163
    store->rval()->accept(this);
dvander@195
   164
    store->lval()->store(emitter_);
dvander@195
   165
}
dvander@195
   166
dvander@195
   167
static inline Opcode
dvander@195
   168
TokenToOpcode(TokenKind kind)
dvander@195
   169
{
dvander@195
   170
    switch (kind) {
dvander@195
   171
      case TOK_PLUS:
dvander@195
   172
        return OP_ADD;
dvander@195
   173
      case TOK_MINUS:
dvander@195
   174
        return OP_SUB;
dvander@195
   175
      case TOK_STAR:
dvander@195
   176
        return OP_MUL;
dvander@195
   177
      case TOK_SLASH:
dvander@195
   178
        return OP_DIV;
dvander@195
   179
      case TOK_PERCENT:
dvander@195
   180
        return OP_MOD;
dvander@195
   181
      case TOK_SHR:
dvander@195
   182
        return OP_SHR;
dvander@195
   183
      case TOK_USHR:
dvander@195
   184
        return OP_USHR;
dvander@195
   185
      case TOK_SHL:
dvander@195
   186
        return OP_SHL;
dvander@195
   187
      case TOK_BITAND:
dvander@195
   188
        return OP_BITAND;
dvander@195
   189
      case TOK_BITOR:
dvander@195
   190
        return OP_BITOR;
dvander@195
   191
      case TOK_GT:
dvander@195
   192
          return OP_GT;
dvander@195
   193
      case TOK_GE:
dvander@195
   194
          return OP_GE;
dvander@195
   195
      case TOK_LT:
dvander@195
   196
          return OP_LT;
dvander@195
   197
      case TOK_LE:
dvander@195
   198
          return OP_LE;
dvander@195
   199
      case TOK_EQUALS:
dvander@195
   200
          return OP_EQ;
dvander@195
   201
      case TOK_NOTEQUALS:
dvander@195
   202
          return OP_NE;
dvander@195
   203
      default:
dvander@195
   204
        assert(kind == TOK_BITXOR);
dvander@195
   205
        return OP_BITXOR;
dvander@195
   206
    }
dvander@195
   207
}
dvander@195
   208
dvander@195
   209
void
dvander@195
   210
HIRTranslator::visitBinary(HBinary *binary)
dvander@195
   211
{
dvander@195
   212
    binary->left()->accept(this);
dvander@195
   213
    binary->right()->accept(this);
dvander@195
   214
dvander@195
   215
    // We define three sets of math operators:
dvander@195
   216
    //
dvander@195
   217
    //  (1) ADD, SUB, MUL, DIV, MOD, which take two equal types and produce
dvander@195
   218
    //      the same type.
dvander@195
   219
    //  (2) LT, LE, GE, GT, EQ, NE, which take two equal types and produce
dvander@195
   220
    //      a boolean.
dvander@195
   221
    //  (3) SHL, SR, USHR, BITAND, BITOR, BITXOR, BITNOT, which take two
dvander@195
   222
    //      equal integer types and return that integer type.
dvander@195
   223
    //
dvander@195
   224
    Opcode op = TokenToOpcode(binary->token());
dvander@195
   225
dvander@195
   226
    if (op >= OP_ADD && op <= OP_NE) {
dvander@195
   227
        if (binary->type()->isFloat())
dvander@195
   228
            op = Opcode(int(op) + int(OP_ADD_F - OP_ADD));
dvander@195
   229
    } else {
dvander@195
   230
        assert(binary->type()->isInt32());
dvander@195
   231
    }
dvander@195
   232
dvander@195
   233
    __ binary(op);
dvander@195
   234
}
dvander@195
   235
dvander@195
   236
void
dvander@195
   237
HIRTranslator::visitConvert(HConvert *convert)
dvander@195
   238
{
dvander@195
   239
    convert->in()->accept(this);
dvander@195
   240
    __ unary(convert->opcode());
dvander@195
   241
}
dvander@195
   242
dvander@195
   243
void
dvander@195
   244
ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
dvander@195
   245
{
dvander@195
   246
    HIRTranslator translator(zone, emitter);
dvander@195
   247
    translator.translate(hir);
dvander@195
   248
}