src/compiler/HIR.cpp
author David Anderson <dvander@alliedmods.net>
Wed Dec 26 17:14:12 2012 -0800 (2012-12-26)
changeset 241 18f3010a358c
parent 236 072f1114ea5d
child 245 9371f058625a
permissions -rw-r--r--
Implement |const| keyword.
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@221
    19
#include "AST.h"
dvander@195
    20
#include "HIR.h"
dvander@195
    21
#include "BytecodeEmitter.h"
dvander@234
    22
#include "../Strings.h"
dvander@196
    23
#include "../Heap-inl.h"
dvander@196
    24
#include "../Handles-inl.h"
dvander@195
    25
dvander@195
    26
using namespace ke;
dvander@195
    27
dvander@195
    28
class HIRTranslator : public HIRVisitor
dvander@195
    29
{
dvander@195
    30
  public:
dvander@195
    31
    HIRTranslator(Zone *zone, BytecodeEmitter &emitter)
dvander@195
    32
      : zone_(zone),
dvander@195
    33
        emitter_(emitter)
dvander@195
    34
    {
dvander@195
    35
    }
dvander@195
    36
dvander@195
    37
    void translate(HIR *hir) {
dvander@195
    38
        hir->accept(this);
dvander@195
    39
    }
dvander@195
    40
dvander@195
    41
    void visitFloat(HFloat *hir);
dvander@195
    42
    void visitInteger(HInteger *hir);
dvander@234
    43
    void visitArray(HArray *hir);
dvander@195
    44
    void visitCall(HCall *call);
dvander@195
    45
    void visitStore(HStore *store);
dvander@195
    46
    void visitBinary(HBinary *binary);
dvander@195
    47
    void visitLocal(HLocal *local);
dvander@195
    48
    void visitGlobal(HGlobal *global);
dvander@195
    49
    void visitConvert(HConvert *convert);
dvander@212
    50
    void visitIndex(HIndex *index);
dvander@218
    51
    void visitPostIncDec(HPostIncDec *hir);
dvander@222
    52
    void visitToRef(HToRef *hir);
dvander@195
    53
dvander@195
    54
  private:
dvander@195
    55
    Zone *zone_;
dvander@195
    56
    BytecodeEmitter &emitter_;
dvander@195
    57
};
dvander@195
    58
dvander@195
    59
#define __ emitter_.
dvander@195
    60
dvander@195
    61
void
dvander@195
    62
HIRTranslator::visitFloat(HFloat *hir)
dvander@195
    63
{
dvander@195
    64
    __ float_(hir->value());
dvander@195
    65
}
dvander@195
    66
dvander@195
    67
void
dvander@195
    68
HIRTranslator::visitInteger(HInteger *hir)
dvander@195
    69
{
dvander@195
    70
    __ int_(hir->value());
dvander@195
    71
}
dvander@195
    72
dvander@195
    73
void
dvander@234
    74
HIRTranslator::visitArray(HArray *hir)
dvander@234
    75
{
dvander@234
    76
    __ object(hir->array());
dvander@234
    77
dvander@236
    78
    if (hir->duplicate())
dvander@234
    79
        __ duparray(); 
dvander@234
    80
}
dvander@234
    81
dvander@234
    82
void
dvander@195
    83
HIRTranslator::visitCall(HCall *call)
dvander@195
    84
{
dvander@195
    85
    Local<FunctionType> fun(zone_, FunctionType::cast(call->callee()->type()));
dvander@195
    86
    
dvander@195
    87
    assert(call->args()->length() == fun->parameters()->length());
dvander@195
    88
dvander@221
    89
    __ note_position(call->node()->pos());
dvander@221
    90
dvander@195
    91
    unsigned argc = call->args()->length();
dvander@195
    92
    for (size_t i = call->args()->length() - 1; i < call->args()->length(); i--) {
dvander@195
    93
        HIR *hir = call->args()->at(i);
dvander@195
    94
        hir->accept(this);
dvander@195
    95
    }
dvander@195
    96
dvander@195
    97
    call->callee()->accept(this);
dvander@195
    98
    __ call(fun, argc);
dvander@195
    99
}
dvander@195
   100
dvander@195
   101
void
dvander@195
   102
HGlobal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
dvander@195
   103
{
dvander@195
   104
}
dvander@195
   105
dvander@195
   106
void
dvander@215
   107
HGlobal::hold(BytecodeEmitter &emitter_)
dvander@215
   108
{
dvander@215
   109
}
dvander@215
   110
dvander@215
   111
void
dvander@218
   112
HGlobal::swapAndPick(BytecodeEmitter &emitter_)
dvander@218
   113
{
dvander@218
   114
    __ dup();
dvander@218
   115
}
dvander@218
   116
dvander@218
   117
void
dvander@195
   118
HGlobal::store(BytecodeEmitter &emitter_)
dvander@195
   119
{
dvander@195
   120
    __ setglobal(sym_);
dvander@195
   121
}
dvander@195
   122
dvander@195
   123
void
dvander@195
   124
HGlobal::load(BytecodeEmitter &emitter_)
dvander@195
   125
{
dvander@195
   126
    __ getglobal(sym_);
dvander@195
   127
}
dvander@195
   128
dvander@222
   129
bool
dvander@222
   130
HGlobal::ref(BytecodeEmitter &emitter_)
dvander@222
   131
{
dvander@222
   132
    return false;
dvander@222
   133
}
dvander@222
   134
dvander@222
   135
static inline Type *
dvander@222
   136
MaybeDereference(Type *type)
dvander@222
   137
{
dvander@222
   138
    if (type->isReference())
dvander@222
   139
        return ReferenceType::cast(type)->contained();
dvander@222
   140
    return type;
dvander@222
   141
}
dvander@222
   142
dvander@222
   143
HLocal::HLocal(AstNode *node, VariableSymbol *sym)
dvander@222
   144
  : HLValue(node, MaybeDereference(sym->type())),
dvander@222
   145
    sym_(sym)
dvander@222
   146
{
dvander@222
   147
}
dvander@222
   148
dvander@195
   149
void
dvander@195
   150
HLocal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
dvander@195
   151
{
dvander@220
   152
    if (sym_->type()->isReference()) {
dvander@220
   153
        if (sym_->storage() == VariableSymbol::Local)
dvander@220
   154
            __ getlocal(sym_);
dvander@220
   155
        else if (sym_->storage() == VariableSymbol::Arg)
dvander@220
   156
            __ getarg(sym_);
dvander@220
   157
        else
dvander@220
   158
            assert(false);
dvander@220
   159
    }
dvander@195
   160
}
dvander@195
   161
dvander@195
   162
void
dvander@215
   163
HLocal::hold(BytecodeEmitter &emitter_)
dvander@215
   164
{
dvander@215
   165
    if (sym_->type()->isReference())
dvander@215
   166
        __ dup();
dvander@215
   167
}
dvander@215
   168
dvander@215
   169
void
dvander@218
   170
HLocal::swapAndPick(BytecodeEmitter &emitter_)
dvander@218
   171
{
dvander@218
   172
    if (sym_->type()->isReference()) {
dvander@218
   173
        __ swap();
dvander@218
   174
        __ pick2();
dvander@218
   175
    } else {
dvander@218
   176
        __ dup();
dvander@218
   177
    }
dvander@218
   178
}
dvander@218
   179
dvander@218
   180
void
dvander@195
   181
HLocal::store(BytecodeEmitter &emitter_)
dvander@195
   182
{
dvander@220
   183
    if (sym_->type()->isReference()) {
dvander@222
   184
        __ setref(ReferenceType::cast(sym_->type())->contained());
dvander@220
   185
    } else {
dvander@220
   186
        if (sym_->storage() == VariableSymbol::Local)
dvander@220
   187
            __ setlocal(sym_);
dvander@220
   188
        else if (sym_->storage() == VariableSymbol::Arg)
dvander@220
   189
            __ setarg(sym_);
dvander@220
   190
        else
dvander@220
   191
            assert(false);
dvander@220
   192
    }
dvander@195
   193
}
dvander@195
   194
dvander@195
   195
void
dvander@195
   196
HLocal::load(BytecodeEmitter &emitter_)
dvander@195
   197
{
dvander@195
   198
    if (sym_->type()->isReference())
dvander@222
   199
        __ getref(ReferenceType::cast(sym_->type())->contained());
dvander@220
   200
    else if (sym_->storage() == VariableSymbol::Local)
dvander@220
   201
        __ getlocal(sym_);
dvander@220
   202
    else if (sym_->storage() == VariableSymbol::Arg)
dvander@220
   203
        __ getarg(sym_);
dvander@195
   204
    else
dvander@220
   205
        assert(false);
dvander@195
   206
}
dvander@195
   207
dvander@222
   208
bool
dvander@222
   209
HLocal::ref(BytecodeEmitter &emitter_)
dvander@222
   210
{
dvander@222
   211
    if (sym_->storage() == VariableSymbol::Heap) {
dvander@222
   212
        // Closing over a reference should never pass SemA.
dvander@222
   213
        assert(!sym_->type()->isReference());
dvander@222
   214
dvander@222
   215
        // We don't support direct references to heap-allocated locals. This
dvander@222
   216
        // should probably be banned in SemA? But for now, just assert. :TODO:
dvander@222
   217
        assert(false);
dvander@222
   218
        return false;
dvander@222
   219
    }
dvander@222
   220
        
dvander@222
   221
    if (sym_->type()->isReference()) {
dvander@222
   222
        if (sym_->storage() == VariableSymbol::Local)
dvander@222
   223
            __ getlocal(sym_);
dvander@222
   224
        else if (sym_->storage() == VariableSymbol::Arg)
dvander@222
   225
            __ getarg(sym_);
dvander@222
   226
        else
dvander@222
   227
            assert(false);
dvander@222
   228
    } else {
dvander@222
   229
        __ newref(sym_);
dvander@222
   230
    }
dvander@222
   231
dvander@222
   232
    return true;
dvander@222
   233
}
dvander@222
   234
dvander@195
   235
void
dvander@195
   236
HIndex::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
dvander@195
   237
{
dvander@221
   238
    __ note_position(node()->pos());
dvander@195
   239
    left_->accept(visitor);
dvander@195
   240
    right_->accept(visitor);
dvander@195
   241
}
dvander@195
   242
dvander@195
   243
void
dvander@215
   244
HIndex::hold(BytecodeEmitter &emitter_)
dvander@215
   245
{
dvander@215
   246
    __ dup2();
dvander@215
   247
}
dvander@215
   248
dvander@215
   249
void
dvander@218
   250
HIndex::swapAndPick(BytecodeEmitter &emitter_)
dvander@218
   251
{
dvander@218
   252
    // BASE INDEX VALUE
dvander@218
   253
    __ roll3();         // INDEX VALUE BASE
dvander@218
   254
    __ roll3();         // VALUE BASE INDEX
dvander@218
   255
    __ pick3();         // VALUE BASE INDEX VALUE
dvander@218
   256
}
dvander@218
   257
dvander@218
   258
void
dvander@195
   259
HIndex::store(BytecodeEmitter &emitter_)
dvander@195
   260
{
dvander@195
   261
    __ setelem(type());
dvander@195
   262
}
dvander@195
   263
dvander@195
   264
void
dvander@195
   265
HIndex::load(BytecodeEmitter &emitter_)
dvander@195
   266
{
dvander@195
   267
    __ getelem(type());
dvander@195
   268
}
dvander@195
   269
dvander@222
   270
bool
dvander@222
   271
HIndex::ref(BytecodeEmitter &emitter_)
dvander@222
   272
{
dvander@222
   273
    return false;
dvander@222
   274
}
dvander@222
   275
dvander@195
   276
void
dvander@195
   277
HIRTranslator::visitLocal(HLocal *local)
dvander@195
   278
{
dvander@195
   279
    local->bind(this, emitter_);
dvander@195
   280
    local->load(emitter_);
dvander@195
   281
}
dvander@195
   282
dvander@195
   283
void
dvander@212
   284
HIRTranslator::visitIndex(HIndex *index)
dvander@212
   285
{
dvander@212
   286
    index->bind(this, emitter_);
dvander@212
   287
    index->load(emitter_);
dvander@212
   288
}
dvander@212
   289
dvander@212
   290
void
dvander@195
   291
HIRTranslator::visitGlobal(HGlobal *global)
dvander@195
   292
{
dvander@220
   293
    global->bind(this, emitter_);
dvander@220
   294
    global->load(emitter_);
dvander@195
   295
}
dvander@195
   296
dvander@195
   297
static inline Opcode
dvander@195
   298
TokenToOpcode(TokenKind kind)
dvander@195
   299
{
dvander@195
   300
    switch (kind) {
dvander@195
   301
      case TOK_PLUS:
dvander@215
   302
      case TOK_ASSIGN_ADD:
dvander@217
   303
      case TOK_INCREMENT:
dvander@195
   304
        return OP_ADD;
dvander@195
   305
      case TOK_MINUS:
dvander@215
   306
      case TOK_ASSIGN_SUB:
dvander@217
   307
      case TOK_DECREMENT:
dvander@195
   308
        return OP_SUB;
dvander@195
   309
      case TOK_STAR:
dvander@215
   310
      case TOK_ASSIGN_MUL:
dvander@195
   311
        return OP_MUL;
dvander@195
   312
      case TOK_SLASH:
dvander@215
   313
      case TOK_ASSIGN_DIV:
dvander@195
   314
        return OP_DIV;
dvander@195
   315
      case TOK_PERCENT:
dvander@215
   316
      case TOK_ASSIGN_MOD:
dvander@195
   317
        return OP_MOD;
dvander@195
   318
      case TOK_SHR:
dvander@215
   319
      case TOK_ASSIGN_SHR:
dvander@195
   320
        return OP_SHR;
dvander@195
   321
      case TOK_USHR:
dvander@215
   322
      case TOK_ASSIGN_USHR:
dvander@195
   323
        return OP_USHR;
dvander@195
   324
      case TOK_SHL:
dvander@215
   325
      case TOK_ASSIGN_SHL:
dvander@195
   326
        return OP_SHL;
dvander@195
   327
      case TOK_BITAND:
dvander@215
   328
      case TOK_ASSIGN_BITAND:
dvander@195
   329
        return OP_BITAND;
dvander@195
   330
      case TOK_BITOR:
dvander@215
   331
      case TOK_ASSIGN_BITOR:
dvander@195
   332
        return OP_BITOR;
dvander@195
   333
      case TOK_GT:
dvander@195
   334
          return OP_GT;
dvander@195
   335
      case TOK_GE:
dvander@195
   336
          return OP_GE;
dvander@195
   337
      case TOK_LT:
dvander@195
   338
          return OP_LT;
dvander@195
   339
      case TOK_LE:
dvander@195
   340
          return OP_LE;
dvander@195
   341
      case TOK_EQUALS:
dvander@195
   342
          return OP_EQ;
dvander@195
   343
      case TOK_NOTEQUALS:
dvander@195
   344
          return OP_NE;
dvander@195
   345
      default:
dvander@195
   346
        assert(kind == TOK_BITXOR);
dvander@195
   347
        return OP_BITXOR;
dvander@195
   348
    }
dvander@195
   349
}
dvander@195
   350
dvander@195
   351
void
dvander@215
   352
HIRTranslator::visitStore(HStore *store)
dvander@215
   353
{
dvander@215
   354
    store->lval()->bind(this, emitter_);
dvander@236
   355
dvander@215
   356
    if (store->kind() == TOK_ASSIGN) {
dvander@236
   357
        // Fixed-length arrays and structs have copy semantics.
dvander@236
   358
        Local<Type> type(zone_, store->lval()->type());
dvander@236
   359
        if (type->isArray() && ArrayType::cast(type)->isFixedLength()) {
dvander@236
   360
            store->lval()->load(emitter_);
dvander@236
   361
            store->rval()->accept(this);
dvander@236
   362
            __ copyarray();
dvander@236
   363
        } else if (type->isStruct()) {
dvander@236
   364
            store->lval()->load(emitter_);
dvander@236
   365
            store->rval()->accept(this);
dvander@236
   366
            __ copystruct();
dvander@236
   367
        } else {
dvander@236
   368
            store->rval()->accept(this);
dvander@236
   369
            store->lval()->store(emitter_);
dvander@236
   370
        }
dvander@215
   371
    } else {
dvander@215
   372
        // Advanced case: dup the ref, load, op, store.
dvander@215
   373
        store->lval()->hold(emitter_);
dvander@215
   374
        store->lval()->load(emitter_);
dvander@215
   375
        store->rval()->accept(this);
dvander@215
   376
        __ binary(TokenToOpcode(store->kind()));
dvander@236
   377
        store->lval()->store(emitter_);
dvander@215
   378
    }
dvander@215
   379
}
dvander@215
   380
dvander@215
   381
void
dvander@218
   382
HIRTranslator::visitPostIncDec(HPostIncDec *hir)
dvander@218
   383
{
dvander@218
   384
    hir->lval()->bind(this, emitter_);
dvander@218
   385
    hir->lval()->hold(emitter_);
dvander@218
   386
    hir->lval()->load(emitter_);
dvander@218
   387
    hir->lval()->swapAndPick(emitter_);
dvander@218
   388
    hir->rval()->accept(this);
dvander@218
   389
    __ binary(TokenToOpcode(hir->kind()));
dvander@218
   390
    hir->lval()->store(emitter_);
dvander@218
   391
    __ pop();
dvander@218
   392
}
dvander@218
   393
dvander@218
   394
void
dvander@195
   395
HIRTranslator::visitBinary(HBinary *binary)
dvander@195
   396
{
dvander@195
   397
    binary->left()->accept(this);
dvander@195
   398
    binary->right()->accept(this);
dvander@195
   399
dvander@195
   400
    // We define three sets of math operators:
dvander@195
   401
    //
dvander@195
   402
    //  (1) ADD, SUB, MUL, DIV, MOD, which take two equal types and produce
dvander@195
   403
    //      the same type.
dvander@195
   404
    //  (2) LT, LE, GE, GT, EQ, NE, which take two equal types and produce
dvander@195
   405
    //      a boolean.
dvander@195
   406
    //  (3) SHL, SR, USHR, BITAND, BITOR, BITXOR, BITNOT, which take two
dvander@195
   407
    //      equal integer types and return that integer type.
dvander@195
   408
    //
dvander@195
   409
    Opcode op = TokenToOpcode(binary->token());
dvander@195
   410
dvander@221
   411
    if (op == OP_DIV)
dvander@221
   412
        __ note_position(binary->node()->pos());
dvander@221
   413
dvander@195
   414
    if (op >= OP_ADD && op <= OP_NE) {
dvander@195
   415
        if (binary->type()->isFloat())
dvander@195
   416
            op = Opcode(int(op) + int(OP_ADD_F - OP_ADD));
dvander@195
   417
    } else {
dvander@195
   418
        assert(binary->type()->isInt32());
dvander@195
   419
    }
dvander@195
   420
dvander@195
   421
    __ binary(op);
dvander@195
   422
}
dvander@195
   423
dvander@195
   424
void
dvander@195
   425
HIRTranslator::visitConvert(HConvert *convert)
dvander@195
   426
{
dvander@195
   427
    convert->in()->accept(this);
dvander@195
   428
    __ unary(convert->opcode());
dvander@195
   429
}
dvander@195
   430
dvander@195
   431
void
dvander@222
   432
HIRTranslator::visitToRef(HToRef *hir)
dvander@222
   433
{
dvander@222
   434
    HIR *in = hir->in();
dvander@222
   435
dvander@222
   436
    // See if we can bind a direct reference.
dvander@222
   437
    if (in->isLValue() && in->toLValue()->ref(emitter_))
dvander@222
   438
        return;
dvander@222
   439
dvander@222
   440
    // No, we can't. So instead we create an on-stack reference.
dvander@222
   441
    in->accept(this);
dvander@222
   442
    __ slotref_lifo();
dvander@222
   443
}
dvander@222
   444
dvander@222
   445
void
dvander@195
   446
ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
dvander@195
   447
{
dvander@195
   448
    HIRTranslator translator(zone, emitter);
dvander@195
   449
    translator.translate(hir);
dvander@195
   450
}