src/compiler/HIR.h
author David Anderson <dvander@alliedmods.net>
Sat Dec 22 23:18:57 2012 -0800 (2012-12-22)
changeset 233 bbb498ccb4ac
parent 222 0cde1379b29f
child 234 26e3035cdffc
permissions -rw-r--r--
Re-add enum support.
dvander@195
     1
/*
dvander@195
     2
 * Copyright (C) 2012 David Anderson
dvander@195
     3
 *
dvander@195
     4
 * This file is part of SourcePawn.
dvander@195
     5
 *
dvander@195
     6
 * SourcePawn is free software: you can redistribute it and/or modify it under
dvander@195
     7
 * the terms of the GNU General Public License as published by the Free
dvander@195
     8
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@195
     9
 * any later version.
dvander@195
    10
 * 
dvander@195
    11
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@195
    12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@195
    13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@195
    14
 *
dvander@195
    15
 * You should have received a copy of the GNU General Public License along with
dvander@195
    16
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
dvander@195
    17
 */
dvander@195
    18
#ifndef _include_sp2_hir_h_
dvander@195
    19
#define _include_sp2_hir_h_
dvander@195
    20
dvander@195
    21
#include "../Types.h"
dvander@195
    22
#include "../PoolAllocator.h"
dvander@195
    23
#include "../Opcodes.h"
dvander@195
    24
#include "Symbols.h"
dvander@195
    25
dvander@195
    26
namespace ke {
dvander@195
    27
dvander@195
    28
#define HIR_OPS(_)                      \
dvander@195
    29
    _(Call)                             \
dvander@195
    30
    _(Integer)                          \
dvander@195
    31
    _(Float)                            \
dvander@195
    32
    _(Store)                            \
dvander@222
    33
    _(ToRef)                            \
dvander@195
    34
    /* Special LValue types */          \
dvander@195
    35
    _(Index)                            \
dvander@195
    36
    _(Local)                            \
dvander@195
    37
    _(Global)                           \
dvander@195
    38
    /* End LValues */                   \
dvander@195
    39
    _(Binary)                           \
dvander@218
    40
    _(Convert)                          \
dvander@218
    41
    _(PostIncDec)
dvander@195
    42
dvander@195
    43
// Forward declarations.
dvander@195
    44
#define _(name)    class H##name;
dvander@195
    45
HIR_OPS(_)
dvander@195
    46
#undef _
dvander@195
    47
dvander@195
    48
class HIRVisitor;
dvander@221
    49
class AstNode;
dvander@222
    50
class HLValue;
dvander@195
    51
dvander@195
    52
class HIR : public PoolObject
dvander@195
    53
{
dvander@195
    54
  public:
dvander@195
    55
    enum HOp {
dvander@195
    56
#define _(name) k##name,
dvander@195
    57
        HIR_OPS(_)
dvander@195
    58
#undef _
dvander@195
    59
        kTotalOps
dvander@195
    60
    };
dvander@195
    61
dvander@195
    62
  public:
dvander@221
    63
    HIR(AstNode *node, Type *type)
dvander@221
    64
      : node_(node),
dvander@221
    65
        type_(type)
dvander@195
    66
    {
dvander@195
    67
    }
dvander@195
    68
dvander@195
    69
    Handle<Type> type() {
dvander@195
    70
        return type_;
dvander@195
    71
    }
dvander@221
    72
    AstNode *node() const {
dvander@221
    73
        return node_;
dvander@221
    74
    }
dvander@195
    75
dvander@195
    76
    virtual bool isLValue() const {
dvander@195
    77
        return false;
dvander@195
    78
    }
dvander@195
    79
dvander@195
    80
    virtual HOp op() const = 0;
dvander@195
    81
    virtual void accept(HIRVisitor *visitor) = 0;
dvander@195
    82
dvander@222
    83
#define _(name)                                         \
dvander@222
    84
    bool is##name() const {                             \
dvander@222
    85
        return op() == k##name;                         \
dvander@222
    86
    }                                                   \
dvander@222
    87
    H##name *to##name() {                               \
dvander@222
    88
        assert(is##name());                             \
dvander@222
    89
        return reinterpret_cast<H##name *>(this);       \
dvander@222
    90
    }
dvander@222
    91
    HIR_OPS(_)
dvander@222
    92
#undef _
dvander@222
    93
dvander@222
    94
    HLValue *toLValue() {
dvander@222
    95
        assert(isLValue());
dvander@222
    96
        return reinterpret_cast<HLValue *>(this);
dvander@222
    97
    }
dvander@222
    98
dvander@195
    99
  private:
dvander@221
   100
    AstNode *node_;
dvander@195
   101
    ScopedRoot<Type> type_;
dvander@195
   102
};
dvander@195
   103
dvander@195
   104
class BytecodeEmitter;
dvander@195
   105
dvander@195
   106
class HIRVisitor
dvander@195
   107
{
dvander@195
   108
  public:
dvander@195
   109
#define _(name)                                 \
dvander@195
   110
    virtual void visit##name(H##name *hir) {    \
dvander@195
   111
        assert(false);                          \
dvander@195
   112
    }
dvander@195
   113
    HIR_OPS(_)
dvander@195
   114
#undef _
dvander@195
   115
};
dvander@195
   116
dvander@195
   117
typedef PoolList<HIR *> HIRList;
dvander@195
   118
dvander@195
   119
#define DEFINE_HIR(name)                        \
dvander@195
   120
    virtual HOp op() const {                    \
dvander@195
   121
        return k##name;                         \
dvander@195
   122
    }                                           \
dvander@195
   123
    virtual void accept(HIRVisitor *visitor) {  \
dvander@195
   124
        visitor->visit##name(this);             \
dvander@195
   125
    }
dvander@195
   126
dvander@195
   127
class HInteger : public HIR
dvander@195
   128
{
dvander@195
   129
  public:
dvander@221
   130
    HInteger(AstNode *node, Type *type, int value)
dvander@221
   131
      : HIR(node, type),
dvander@195
   132
        value_(value)
dvander@195
   133
    {
dvander@195
   134
    }
dvander@195
   135
dvander@195
   136
    DEFINE_HIR(Integer);
dvander@195
   137
    int value() const {
dvander@195
   138
        return value_;
dvander@195
   139
    }
dvander@195
   140
dvander@195
   141
  private:
dvander@195
   142
    int value_;
dvander@195
   143
};
dvander@195
   144
dvander@195
   145
class HConvert : public HIR
dvander@195
   146
{
dvander@195
   147
  public:
dvander@221
   148
    HConvert(AstNode *node, Type *type, Opcode op, HIR *in)
dvander@221
   149
      : HIR(node, type),
dvander@195
   150
        op_(op),
dvander@195
   151
        in_(in)
dvander@195
   152
    {
dvander@195
   153
    }
dvander@195
   154
dvander@195
   155
    DEFINE_HIR(Convert);
dvander@195
   156
    Opcode opcode() const {
dvander@195
   157
        return op_;
dvander@195
   158
    }
dvander@195
   159
    HIR *in() const {
dvander@195
   160
        return in_;
dvander@195
   161
    }
dvander@195
   162
dvander@195
   163
  private:
dvander@195
   164
    Opcode op_;
dvander@195
   165
    HIR *in_;
dvander@195
   166
};
dvander@195
   167
dvander@195
   168
class HLValue : public HIR
dvander@195
   169
{
dvander@195
   170
  public:
dvander@221
   171
    HLValue(AstNode *node, Type *type)
dvander@221
   172
      : HIR(node, type)
dvander@195
   173
    {
dvander@195
   174
    }
dvander@195
   175
dvander@195
   176
    // Pushes a reference to the LValue on the stack.
dvander@195
   177
    virtual void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_) = 0;
dvander@215
   178
    
dvander@215
   179
    // Duplicates a stack reference.
dvander@215
   180
    virtual void hold(BytecodeEmitter &emitter_) = 0;
dvander@195
   181
dvander@218
   182
    // Reorders the stack for a post-increment operation:
dvander@218
   183
    //   REF VAL -> VAL REF VAL
dvander@218
   184
    virtual void swapAndPick(BytecodeEmitter &emitter_) = 0;
dvander@218
   185
dvander@195
   186
    // Given a stack layout of the form:
dvander@195
   187
    //  [-1]    value
dvander@195
   188
    //  [-2..n] ref
dvander@195
   189
    //
dvander@195
   190
    // Emits a store to the reference.
dvander@195
   191
    virtual void store(BytecodeEmitter &emitter_) = 0;
dvander@195
   192
    virtual void load(BytecodeEmitter &emitter_) = 0;
dvander@195
   193
dvander@222
   194
    // Try to make a direct reference, if semantics allow it. False if the
dvander@222
   195
    // caller must allocate a reference to the stack.
dvander@222
   196
    virtual bool ref(BytecodeEmitter &emitter_) = 0;
dvander@222
   197
dvander@195
   198
    bool isLValue() const {
dvander@195
   199
        return true;
dvander@195
   200
    }
dvander@195
   201
};
dvander@195
   202
dvander@195
   203
class HLocal : public HLValue
dvander@195
   204
{
dvander@195
   205
  public:
dvander@222
   206
    HLocal(AstNode *node, VariableSymbol *sym);
dvander@195
   207
dvander@195
   208
    DEFINE_HIR(Local);
dvander@195
   209
dvander@195
   210
    // Pushes a reference to the LValue on the stack.
dvander@195
   211
    void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_);
dvander@215
   212
    void hold(BytecodeEmitter &emitter_);
dvander@218
   213
    void swapAndPick(BytecodeEmitter &emitter_);
dvander@195
   214
    void store(BytecodeEmitter &emitter_);
dvander@195
   215
    void load(BytecodeEmitter &emitter_);
dvander@222
   216
    bool ref(BytecodeEmitter &emitter_);
dvander@222
   217
dvander@222
   218
    VariableSymbol *sym() const {
dvander@222
   219
        return sym_;
dvander@222
   220
    }
dvander@195
   221
dvander@195
   222
  private:
dvander@195
   223
    VariableSymbol *sym_;
dvander@195
   224
};
dvander@195
   225
dvander@195
   226
class HIndex : public HLValue
dvander@195
   227
{
dvander@195
   228
  public:
dvander@221
   229
    HIndex(AstNode *node, Type *type, HIR *left, HIR *right)
dvander@221
   230
      : HLValue(node, type),
dvander@195
   231
        left_(left),
dvander@195
   232
        right_(right)
dvander@195
   233
    {
dvander@195
   234
    }
dvander@195
   235
dvander@195
   236
    DEFINE_HIR(Index);
dvander@195
   237
dvander@195
   238
    void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_);
dvander@215
   239
    void hold(BytecodeEmitter &emitter_);
dvander@218
   240
    void swapAndPick(BytecodeEmitter &emitter_);
dvander@195
   241
    void store(BytecodeEmitter &emitter_);
dvander@195
   242
    void load(BytecodeEmitter &emitter_);
dvander@222
   243
    bool ref(BytecodeEmitter &emitter_);
dvander@195
   244
dvander@195
   245
  private:
dvander@195
   246
    HIR *left_;
dvander@195
   247
    HIR *right_;
dvander@195
   248
};
dvander@195
   249
dvander@195
   250
class HGlobal : public HLValue
dvander@195
   251
{
dvander@195
   252
  public:
dvander@221
   253
    HGlobal(AstNode *node, Symbol *sym)
dvander@221
   254
      : HLValue(node, sym->type()),
dvander@195
   255
        sym_(sym)
dvander@195
   256
    {
dvander@195
   257
    }
dvander@195
   258
dvander@195
   259
    DEFINE_HIR(Global);
dvander@195
   260
dvander@195
   261
    void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_);
dvander@215
   262
    void hold(BytecodeEmitter &emitter_);
dvander@218
   263
    void swapAndPick(BytecodeEmitter &emitter_);
dvander@195
   264
    void store(BytecodeEmitter &emitter_);
dvander@195
   265
    void load(BytecodeEmitter &emitter_);
dvander@222
   266
    bool ref(BytecodeEmitter &emitter_);
dvander@195
   267
dvander@195
   268
    Symbol *sym() const {
dvander@195
   269
        return sym_;
dvander@195
   270
    }
dvander@195
   271
dvander@195
   272
  private:
dvander@195
   273
    Symbol *sym_;
dvander@195
   274
};
dvander@195
   275
dvander@195
   276
class HBinary : public HIR
dvander@195
   277
{
dvander@195
   278
  public:
dvander@221
   279
    HBinary(AstNode *node, Type *type, TokenKind token, HIR *left, HIR *right)
dvander@221
   280
      : HIR(node, type),
dvander@195
   281
        token_(token),
dvander@195
   282
        left_(left),
dvander@195
   283
        right_(right)
dvander@195
   284
    {
dvander@195
   285
    }
dvander@195
   286
dvander@195
   287
    DEFINE_HIR(Binary);
dvander@195
   288
    TokenKind token() const {
dvander@195
   289
        return token_;
dvander@195
   290
    }
dvander@195
   291
    HIR *left() const {
dvander@195
   292
        return left_;
dvander@195
   293
    }
dvander@195
   294
    HIR *right() const {
dvander@195
   295
        return right_;
dvander@195
   296
    }
dvander@195
   297
dvander@195
   298
  private:
dvander@195
   299
    TokenKind token_;
dvander@195
   300
    HIR *left_;
dvander@195
   301
    HIR *right_;
dvander@195
   302
};
dvander@195
   303
dvander@195
   304
class HFloat : public HIR
dvander@195
   305
{
dvander@195
   306
  public:
dvander@221
   307
    HFloat(AstNode *node, Type *type, float value)
dvander@221
   308
      : HIR(node, type),
dvander@195
   309
        value_(value)
dvander@195
   310
    {
dvander@195
   311
    }
dvander@195
   312
dvander@195
   313
    DEFINE_HIR(Float);
dvander@195
   314
    float value() const {
dvander@195
   315
        return value_;
dvander@195
   316
    }
dvander@195
   317
dvander@195
   318
  private:
dvander@195
   319
    float value_;
dvander@195
   320
};
dvander@195
   321
dvander@195
   322
class HStore : public HIR
dvander@195
   323
{
dvander@195
   324
  public:
dvander@221
   325
    HStore(AstNode *node, HLValue *lval, HIR *rval)
dvander@221
   326
      : HIR(node, lval->type()),
dvander@215
   327
        kind_(TOK_ASSIGN),
dvander@215
   328
        lval_(lval),
dvander@215
   329
        rval_(rval)
dvander@215
   330
    {
dvander@215
   331
    }
dvander@215
   332
dvander@221
   333
    HStore(AstNode *node, TokenKind kind, HLValue *lval, HIR *rval)
dvander@221
   334
      : HIR(node, lval->type()),
dvander@215
   335
        kind_(kind),
dvander@195
   336
        lval_(lval),
dvander@195
   337
        rval_(rval)
dvander@195
   338
    {
dvander@195
   339
    }
dvander@195
   340
dvander@195
   341
    DEFINE_HIR(Store);
dvander@195
   342
dvander@195
   343
    HLValue *lval() const {
dvander@195
   344
        return lval_;
dvander@195
   345
    }
dvander@195
   346
    HIR *rval() const {
dvander@195
   347
        return rval_;
dvander@195
   348
    }
dvander@215
   349
    TokenKind kind() const {
dvander@215
   350
        return kind_;
dvander@215
   351
    }
dvander@195
   352
dvander@195
   353
  private:
dvander@216
   354
    TokenKind kind_;
dvander@195
   355
    HLValue *lval_;
dvander@195
   356
    HIR *rval_;
dvander@195
   357
};
dvander@195
   358
dvander@218
   359
class HPostIncDec : public HIR
dvander@218
   360
{
dvander@218
   361
  public:
dvander@221
   362
    HPostIncDec(AstNode *node, TokenKind kind, HLValue *lval, HIR *rval)
dvander@221
   363
      : HIR(node, lval->type()),
dvander@218
   364
        kind_(kind),
dvander@218
   365
        lval_(lval),
dvander@218
   366
        rval_(rval)
dvander@218
   367
    {
dvander@218
   368
    }
dvander@218
   369
dvander@218
   370
    DEFINE_HIR(PostIncDec);
dvander@218
   371
dvander@218
   372
    HLValue *lval() const {
dvander@218
   373
        return lval_;
dvander@218
   374
    }
dvander@218
   375
    HIR *rval() const {
dvander@218
   376
        return rval_;
dvander@218
   377
    }
dvander@218
   378
    TokenKind kind() const {
dvander@218
   379
        return kind_;
dvander@218
   380
    }
dvander@218
   381
dvander@218
   382
  private:
dvander@218
   383
    TokenKind kind_;
dvander@218
   384
    HLValue *lval_;
dvander@218
   385
    HIR *rval_;
dvander@218
   386
};
dvander@218
   387
dvander@195
   388
class HCall : public HIR
dvander@195
   389
{
dvander@195
   390
  public:
dvander@221
   391
    HCall(AstNode *node, Type *type, HIR *callee, HIRList *args)
dvander@221
   392
      : HIR(node, type),
dvander@195
   393
        callee_(callee),
dvander@195
   394
        args_(args)
dvander@195
   395
    {
dvander@195
   396
    }
dvander@195
   397
dvander@195
   398
    DEFINE_HIR(Call);
dvander@195
   399
dvander@195
   400
    HIR *callee() const {
dvander@195
   401
        return callee_;
dvander@195
   402
    }
dvander@195
   403
    HIRList *args() const {
dvander@195
   404
        return args_;
dvander@195
   405
    }
dvander@195
   406
dvander@195
   407
  private:
dvander@195
   408
    HIR *callee_;
dvander@195
   409
    HIRList *args_;
dvander@195
   410
};
dvander@195
   411
dvander@222
   412
class HToRef : public HIR
dvander@222
   413
{
dvander@222
   414
  public:
dvander@222
   415
    HToRef(AstNode *node, Type *type, HIR *in)
dvander@222
   416
      : HIR(node, type),
dvander@222
   417
        in_(in)
dvander@222
   418
    {
dvander@222
   419
    }
dvander@222
   420
dvander@222
   421
    DEFINE_HIR(ToRef);
dvander@222
   422
dvander@222
   423
    HIR *in() const {
dvander@222
   424
        return in_;
dvander@222
   425
    }
dvander@222
   426
dvander@222
   427
  private:
dvander@222
   428
    HIR *in_;
dvander@222
   429
};
dvander@222
   430
dvander@195
   431
#undef DEFINE_HIR
dvander@195
   432
dvander@195
   433
void EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir);
dvander@195
   434
dvander@195
   435
}
dvander@195
   436
dvander@195
   437
#endif // _include_sp2_hir_h_