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