src/compiler/HIR.h
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
/*
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@195
    33
    /* Special LValue types */          \
dvander@195
    34
    _(Index)                            \
dvander@195
    35
    _(Local)                            \
dvander@195
    36
    _(Global)                           \
dvander@195
    37
    /* End LValues */                   \
dvander@195
    38
    _(Binary)                           \
dvander@218
    39
    _(Convert)                          \
dvander@218
    40
    _(PostIncDec)
dvander@195
    41
dvander@195
    42
// Forward declarations.
dvander@195
    43
#define _(name)    class H##name;
dvander@195
    44
HIR_OPS(_)
dvander@195
    45
#undef _
dvander@195
    46
dvander@195
    47
class HIRVisitor;
dvander@195
    48
dvander@195
    49
class HIR : public PoolObject
dvander@195
    50
{
dvander@195
    51
  public:
dvander@195
    52
    enum HOp {
dvander@195
    53
#define _(name) k##name,
dvander@195
    54
        HIR_OPS(_)
dvander@195
    55
#undef _
dvander@195
    56
        kTotalOps
dvander@195
    57
    };
dvander@195
    58
dvander@195
    59
  public:
dvander@195
    60
    HIR(Type *type)
dvander@195
    61
      : type_(type)
dvander@195
    62
    {
dvander@195
    63
    }
dvander@195
    64
dvander@195
    65
    Handle<Type> type() {
dvander@195
    66
        return type_;
dvander@195
    67
    }
dvander@195
    68
dvander@195
    69
    virtual bool isLValue() const {
dvander@195
    70
        return false;
dvander@195
    71
    }
dvander@195
    72
dvander@195
    73
    virtual HOp op() const = 0;
dvander@195
    74
    virtual void accept(HIRVisitor *visitor) = 0;
dvander@195
    75
dvander@195
    76
  private:
dvander@195
    77
    ScopedRoot<Type> type_;
dvander@195
    78
};
dvander@195
    79
dvander@195
    80
class BytecodeEmitter;
dvander@195
    81
dvander@195
    82
class HIRVisitor
dvander@195
    83
{
dvander@195
    84
  public:
dvander@195
    85
#define _(name)                                 \
dvander@195
    86
    virtual void visit##name(H##name *hir) {    \
dvander@195
    87
        assert(false);                          \
dvander@195
    88
    }
dvander@195
    89
    HIR_OPS(_)
dvander@195
    90
#undef _
dvander@195
    91
};
dvander@195
    92
dvander@195
    93
typedef PoolList<HIR *> HIRList;
dvander@195
    94
dvander@195
    95
#define DEFINE_HIR(name)                        \
dvander@195
    96
    virtual HOp op() const {                    \
dvander@195
    97
        return k##name;                         \
dvander@195
    98
    }                                           \
dvander@195
    99
    virtual void accept(HIRVisitor *visitor) {  \
dvander@195
   100
        visitor->visit##name(this);             \
dvander@195
   101
    }
dvander@195
   102
dvander@195
   103
class HInteger : public HIR
dvander@195
   104
{
dvander@195
   105
  public:
dvander@195
   106
    HInteger(Type *type, int value)
dvander@195
   107
      : HIR(type),
dvander@195
   108
        value_(value)
dvander@195
   109
    {
dvander@195
   110
    }
dvander@195
   111
dvander@195
   112
    DEFINE_HIR(Integer);
dvander@195
   113
    int value() const {
dvander@195
   114
        return value_;
dvander@195
   115
    }
dvander@195
   116
dvander@195
   117
  private:
dvander@195
   118
    int value_;
dvander@195
   119
};
dvander@195
   120
dvander@195
   121
class HConvert : public HIR
dvander@195
   122
{
dvander@195
   123
  public:
dvander@195
   124
    HConvert(Type *type, Opcode op, HIR *in)
dvander@195
   125
      : HIR(type),
dvander@195
   126
        op_(op),
dvander@195
   127
        in_(in)
dvander@195
   128
    {
dvander@195
   129
    }
dvander@195
   130
dvander@195
   131
    DEFINE_HIR(Convert);
dvander@195
   132
    Opcode opcode() const {
dvander@195
   133
        return op_;
dvander@195
   134
    }
dvander@195
   135
    HIR *in() const {
dvander@195
   136
        return in_;
dvander@195
   137
    }
dvander@195
   138
dvander@195
   139
  private:
dvander@195
   140
    Opcode op_;
dvander@195
   141
    HIR *in_;
dvander@195
   142
};
dvander@195
   143
dvander@195
   144
class HLValue : public HIR
dvander@195
   145
{
dvander@195
   146
  public:
dvander@195
   147
    HLValue(Type *type)
dvander@195
   148
      : HIR(type)
dvander@195
   149
    {
dvander@195
   150
    }
dvander@195
   151
dvander@195
   152
    // Pushes a reference to the LValue on the stack.
dvander@195
   153
    virtual void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_) = 0;
dvander@215
   154
    
dvander@215
   155
    // Duplicates a stack reference.
dvander@215
   156
    virtual void hold(BytecodeEmitter &emitter_) = 0;
dvander@195
   157
dvander@218
   158
    // Reorders the stack for a post-increment operation:
dvander@218
   159
    //   REF VAL -> VAL REF VAL
dvander@218
   160
    virtual void swapAndPick(BytecodeEmitter &emitter_) = 0;
dvander@218
   161
dvander@195
   162
    // Given a stack layout of the form:
dvander@195
   163
    //  [-1]    value
dvander@195
   164
    //  [-2..n] ref
dvander@195
   165
    //
dvander@195
   166
    // Emits a store to the reference.
dvander@195
   167
    virtual void store(BytecodeEmitter &emitter_) = 0;
dvander@195
   168
    virtual void load(BytecodeEmitter &emitter_) = 0;
dvander@195
   169
dvander@195
   170
    bool isLValue() const {
dvander@195
   171
        return true;
dvander@195
   172
    }
dvander@195
   173
};
dvander@195
   174
dvander@195
   175
class HLocal : public HLValue
dvander@195
   176
{
dvander@195
   177
  public:
dvander@195
   178
    HLocal(VariableSymbol *sym)
dvander@195
   179
      : HLValue(sym->type()),
dvander@195
   180
        sym_(sym)
dvander@195
   181
    {
dvander@195
   182
    }
dvander@195
   183
dvander@195
   184
    DEFINE_HIR(Local);
dvander@195
   185
dvander@195
   186
    // Pushes a reference to the LValue on the stack.
dvander@195
   187
    void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_);
dvander@215
   188
    void hold(BytecodeEmitter &emitter_);
dvander@218
   189
    void swapAndPick(BytecodeEmitter &emitter_);
dvander@195
   190
    void store(BytecodeEmitter &emitter_);
dvander@195
   191
    void load(BytecodeEmitter &emitter_);
dvander@195
   192
dvander@195
   193
  private:
dvander@195
   194
    VariableSymbol *sym_;
dvander@195
   195
};
dvander@195
   196
dvander@195
   197
class HIndex : public HLValue
dvander@195
   198
{
dvander@195
   199
  public:
dvander@195
   200
    HIndex(Type *type, HIR *left, HIR *right)
dvander@195
   201
      : HLValue(type),
dvander@195
   202
        left_(left),
dvander@195
   203
        right_(right)
dvander@195
   204
    {
dvander@195
   205
    }
dvander@195
   206
dvander@195
   207
    DEFINE_HIR(Index);
dvander@195
   208
dvander@195
   209
    void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_);
dvander@215
   210
    void hold(BytecodeEmitter &emitter_);
dvander@218
   211
    void swapAndPick(BytecodeEmitter &emitter_);
dvander@195
   212
    void store(BytecodeEmitter &emitter_);
dvander@195
   213
    void load(BytecodeEmitter &emitter_);
dvander@195
   214
dvander@195
   215
  private:
dvander@195
   216
    HIR *left_;
dvander@195
   217
    HIR *right_;
dvander@195
   218
};
dvander@195
   219
dvander@195
   220
class HGlobal : public HLValue
dvander@195
   221
{
dvander@195
   222
  public:
dvander@195
   223
    HGlobal(Symbol *sym)
dvander@195
   224
      : HLValue(sym->type()),
dvander@195
   225
        sym_(sym)
dvander@195
   226
    {
dvander@195
   227
    }
dvander@195
   228
dvander@195
   229
    DEFINE_HIR(Global);
dvander@195
   230
dvander@195
   231
    void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_);
dvander@215
   232
    void hold(BytecodeEmitter &emitter_);
dvander@218
   233
    void swapAndPick(BytecodeEmitter &emitter_);
dvander@195
   234
    void store(BytecodeEmitter &emitter_);
dvander@195
   235
    void load(BytecodeEmitter &emitter_);
dvander@195
   236
dvander@195
   237
    Symbol *sym() const {
dvander@195
   238
        return sym_;
dvander@195
   239
    }
dvander@195
   240
dvander@195
   241
  private:
dvander@195
   242
    Symbol *sym_;
dvander@195
   243
};
dvander@195
   244
dvander@195
   245
class HBinary : public HIR
dvander@195
   246
{
dvander@195
   247
  public:
dvander@195
   248
    HBinary(Type *type, TokenKind token, HIR *left, HIR *right)
dvander@195
   249
      : HIR(type),
dvander@195
   250
        token_(token),
dvander@195
   251
        left_(left),
dvander@195
   252
        right_(right)
dvander@195
   253
    {
dvander@195
   254
    }
dvander@195
   255
dvander@195
   256
    DEFINE_HIR(Binary);
dvander@195
   257
    TokenKind token() const {
dvander@195
   258
        return token_;
dvander@195
   259
    }
dvander@195
   260
    HIR *left() const {
dvander@195
   261
        return left_;
dvander@195
   262
    }
dvander@195
   263
    HIR *right() const {
dvander@195
   264
        return right_;
dvander@195
   265
    }
dvander@195
   266
dvander@195
   267
  private:
dvander@195
   268
    TokenKind token_;
dvander@195
   269
    HIR *left_;
dvander@195
   270
    HIR *right_;
dvander@195
   271
};
dvander@195
   272
dvander@195
   273
class HFloat : public HIR
dvander@195
   274
{
dvander@195
   275
  public:
dvander@195
   276
    HFloat(Type *type, float value)
dvander@195
   277
      : HIR(type),
dvander@195
   278
        value_(value)
dvander@195
   279
    {
dvander@195
   280
    }
dvander@195
   281
dvander@195
   282
    DEFINE_HIR(Float);
dvander@195
   283
    float value() const {
dvander@195
   284
        return value_;
dvander@195
   285
    }
dvander@195
   286
dvander@195
   287
  private:
dvander@195
   288
    float value_;
dvander@195
   289
};
dvander@195
   290
dvander@195
   291
class HStore : public HIR
dvander@195
   292
{
dvander@195
   293
  public:
dvander@195
   294
    HStore(HLValue *lval, HIR *rval)
dvander@195
   295
      : HIR(lval->type()),
dvander@215
   296
        kind_(TOK_ASSIGN),
dvander@215
   297
        lval_(lval),
dvander@215
   298
        rval_(rval)
dvander@215
   299
    {
dvander@215
   300
    }
dvander@215
   301
dvander@215
   302
    HStore(TokenKind kind, HLValue *lval, HIR *rval)
dvander@215
   303
      : HIR(lval->type()),
dvander@215
   304
        kind_(kind),
dvander@195
   305
        lval_(lval),
dvander@195
   306
        rval_(rval)
dvander@195
   307
    {
dvander@195
   308
    }
dvander@195
   309
dvander@195
   310
    DEFINE_HIR(Store);
dvander@195
   311
dvander@195
   312
    HLValue *lval() const {
dvander@195
   313
        return lval_;
dvander@195
   314
    }
dvander@195
   315
    HIR *rval() const {
dvander@195
   316
        return rval_;
dvander@195
   317
    }
dvander@215
   318
    TokenKind kind() const {
dvander@215
   319
        return kind_;
dvander@215
   320
    }
dvander@195
   321
dvander@195
   322
  private:
dvander@216
   323
    TokenKind kind_;
dvander@195
   324
    HLValue *lval_;
dvander@195
   325
    HIR *rval_;
dvander@195
   326
};
dvander@195
   327
dvander@218
   328
class HPostIncDec : public HIR
dvander@218
   329
{
dvander@218
   330
  public:
dvander@218
   331
    HPostIncDec(TokenKind kind, HLValue *lval, HIR *rval)
dvander@218
   332
      : HIR(lval->type()),
dvander@218
   333
        kind_(kind),
dvander@218
   334
        lval_(lval),
dvander@218
   335
        rval_(rval)
dvander@218
   336
    {
dvander@218
   337
    }
dvander@218
   338
dvander@218
   339
    DEFINE_HIR(PostIncDec);
dvander@218
   340
dvander@218
   341
    HLValue *lval() const {
dvander@218
   342
        return lval_;
dvander@218
   343
    }
dvander@218
   344
    HIR *rval() const {
dvander@218
   345
        return rval_;
dvander@218
   346
    }
dvander@218
   347
    TokenKind kind() const {
dvander@218
   348
        return kind_;
dvander@218
   349
    }
dvander@218
   350
dvander@218
   351
  private:
dvander@218
   352
    TokenKind kind_;
dvander@218
   353
    HLValue *lval_;
dvander@218
   354
    HIR *rval_;
dvander@218
   355
};
dvander@218
   356
dvander@195
   357
class HCall : public HIR
dvander@195
   358
{
dvander@195
   359
  public:
dvander@195
   360
    HCall(Type *type, HIR *callee, HIRList *args)
dvander@195
   361
      : HIR(type),
dvander@195
   362
        callee_(callee),
dvander@195
   363
        args_(args)
dvander@195
   364
    {
dvander@195
   365
    }
dvander@195
   366
dvander@195
   367
    DEFINE_HIR(Call);
dvander@195
   368
dvander@195
   369
    HIR *callee() const {
dvander@195
   370
        return callee_;
dvander@195
   371
    }
dvander@195
   372
    HIRList *args() const {
dvander@195
   373
        return args_;
dvander@195
   374
    }
dvander@195
   375
dvander@195
   376
  private:
dvander@195
   377
    HIR *callee_;
dvander@195
   378
    HIRList *args_;
dvander@195
   379
};
dvander@195
   380
dvander@195
   381
#undef DEFINE_HIR
dvander@195
   382
dvander@195
   383
void EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir);
dvander@195
   384
dvander@195
   385
}
dvander@195
   386
dvander@195
   387
#endif // _include_sp2_hir_h_