src/compiler/HIR.h
author David Anderson <dvander@alliedmods.net>
Mon Dec 24 16:43:22 2012 -0800 (2012-12-24)
changeset 237 c77540a61905
parent 236 072f1114ea5d
child 245 9371f058625a
permissions -rw-r--r--
Don't allow declaring void variables.
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@234
    32
    _(String)                           \
dvander@234
    33
    _(Array)                            \
dvander@195
    34
    _(Store)                            \
dvander@222
    35
    _(ToRef)                            \
dvander@195
    36
    /* Special LValue types */          \
dvander@195
    37
    _(Index)                            \
dvander@195
    38
    _(Local)                            \
dvander@195
    39
    _(Global)                           \
dvander@195
    40
    /* End LValues */                   \
dvander@195
    41
    _(Binary)                           \
dvander@218
    42
    _(Convert)                          \
dvander@218
    43
    _(PostIncDec)
dvander@195
    44
dvander@195
    45
// Forward declarations.
dvander@195
    46
#define _(name)    class H##name;
dvander@195
    47
HIR_OPS(_)
dvander@195
    48
#undef _
dvander@195
    49
dvander@195
    50
class HIRVisitor;
dvander@221
    51
class AstNode;
dvander@222
    52
class HLValue;
dvander@234
    53
class Array;
dvander@195
    54
dvander@195
    55
class HIR : public PoolObject
dvander@195
    56
{
dvander@195
    57
  public:
dvander@195
    58
    enum HOp {
dvander@195
    59
#define _(name) k##name,
dvander@195
    60
        HIR_OPS(_)
dvander@195
    61
#undef _
dvander@195
    62
        kTotalOps
dvander@195
    63
    };
dvander@195
    64
dvander@195
    65
  public:
dvander@221
    66
    HIR(AstNode *node, Type *type)
dvander@221
    67
      : node_(node),
dvander@221
    68
        type_(type)
dvander@195
    69
    {
dvander@195
    70
    }
dvander@195
    71
dvander@195
    72
    Handle<Type> type() {
dvander@195
    73
        return type_;
dvander@195
    74
    }
dvander@221
    75
    AstNode *node() const {
dvander@221
    76
        return node_;
dvander@221
    77
    }
dvander@195
    78
dvander@195
    79
    virtual bool isLValue() const {
dvander@195
    80
        return false;
dvander@195
    81
    }
dvander@195
    82
dvander@195
    83
    virtual HOp op() const = 0;
dvander@195
    84
    virtual void accept(HIRVisitor *visitor) = 0;
dvander@195
    85
dvander@222
    86
#define _(name)                                         \
dvander@222
    87
    bool is##name() const {                             \
dvander@222
    88
        return op() == k##name;                         \
dvander@222
    89
    }                                                   \
dvander@222
    90
    H##name *to##name() {                               \
dvander@222
    91
        assert(is##name());                             \
dvander@222
    92
        return reinterpret_cast<H##name *>(this);       \
dvander@222
    93
    }
dvander@222
    94
    HIR_OPS(_)
dvander@222
    95
#undef _
dvander@222
    96
dvander@222
    97
    HLValue *toLValue() {
dvander@222
    98
        assert(isLValue());
dvander@222
    99
        return reinterpret_cast<HLValue *>(this);
dvander@222
   100
    }
dvander@222
   101
dvander@195
   102
  private:
dvander@221
   103
    AstNode *node_;
dvander@195
   104
    ScopedRoot<Type> type_;
dvander@195
   105
};
dvander@195
   106
dvander@195
   107
class BytecodeEmitter;
dvander@195
   108
dvander@195
   109
class HIRVisitor
dvander@195
   110
{
dvander@195
   111
  public:
dvander@195
   112
#define _(name)                                 \
dvander@195
   113
    virtual void visit##name(H##name *hir) {    \
dvander@195
   114
        assert(false);                          \
dvander@195
   115
    }
dvander@195
   116
    HIR_OPS(_)
dvander@195
   117
#undef _
dvander@195
   118
};
dvander@195
   119
dvander@195
   120
typedef PoolList<HIR *> HIRList;
dvander@195
   121
dvander@195
   122
#define DEFINE_HIR(name)                        \
dvander@195
   123
    virtual HOp op() const {                    \
dvander@195
   124
        return k##name;                         \
dvander@195
   125
    }                                           \
dvander@195
   126
    virtual void accept(HIRVisitor *visitor) {  \
dvander@195
   127
        visitor->visit##name(this);             \
dvander@195
   128
    }
dvander@195
   129
dvander@195
   130
class HInteger : public HIR
dvander@195
   131
{
dvander@195
   132
  public:
dvander@221
   133
    HInteger(AstNode *node, Type *type, int value)
dvander@221
   134
      : HIR(node, type),
dvander@195
   135
        value_(value)
dvander@195
   136
    {
dvander@195
   137
    }
dvander@195
   138
dvander@195
   139
    DEFINE_HIR(Integer);
dvander@195
   140
    int value() const {
dvander@195
   141
        return value_;
dvander@195
   142
    }
dvander@195
   143
dvander@195
   144
  private:
dvander@195
   145
    int value_;
dvander@195
   146
};
dvander@195
   147
dvander@234
   148
class HString : public HIR
dvander@234
   149
{
dvander@234
   150
  public:
dvander@234
   151
    HString(AstNode *node, Type *type, String *string)
dvander@234
   152
      : HIR(node, type),
dvander@234
   153
        string_(string)
dvander@234
   154
    {
dvander@234
   155
    }
dvander@234
   156
dvander@234
   157
    DEFINE_HIR(String);
dvander@234
   158
    Handle<String> string() const {
dvander@234
   159
        return string_;
dvander@234
   160
    }
dvander@234
   161
dvander@234
   162
  private:
dvander@234
   163
    ScopedRoot<String> string_;
dvander@234
   164
};
dvander@234
   165
dvander@234
   166
class HArray : public HIR
dvander@234
   167
{
dvander@234
   168
  public:
dvander@236
   169
    HArray(AstNode *node, Type *type, Array *array, bool duplicate)
dvander@234
   170
      : HIR(node, type),
dvander@236
   171
        array_(array),
dvander@236
   172
        duplicate_(duplicate)
dvander@234
   173
    {
dvander@234
   174
    }
dvander@234
   175
dvander@234
   176
    DEFINE_HIR(Array);
dvander@234
   177
    Handle<Array> array() const {
dvander@234
   178
        return array_;
dvander@234
   179
    }
dvander@236
   180
    bool duplicate() const {
dvander@236
   181
        return duplicate_;
dvander@236
   182
    }
dvander@234
   183
dvander@234
   184
  private:
dvander@234
   185
    ScopedRoot<Array> array_;
dvander@236
   186
    bool duplicate_;
dvander@234
   187
};
dvander@234
   188
dvander@195
   189
class HConvert : public HIR
dvander@195
   190
{
dvander@195
   191
  public:
dvander@221
   192
    HConvert(AstNode *node, Type *type, Opcode op, HIR *in)
dvander@221
   193
      : HIR(node, type),
dvander@195
   194
        op_(op),
dvander@195
   195
        in_(in)
dvander@195
   196
    {
dvander@195
   197
    }
dvander@195
   198
dvander@195
   199
    DEFINE_HIR(Convert);
dvander@195
   200
    Opcode opcode() const {
dvander@195
   201
        return op_;
dvander@195
   202
    }
dvander@195
   203
    HIR *in() const {
dvander@195
   204
        return in_;
dvander@195
   205
    }
dvander@195
   206
dvander@195
   207
  private:
dvander@195
   208
    Opcode op_;
dvander@195
   209
    HIR *in_;
dvander@195
   210
};
dvander@195
   211
dvander@195
   212
class HLValue : public HIR
dvander@195
   213
{
dvander@195
   214
  public:
dvander@221
   215
    HLValue(AstNode *node, Type *type)
dvander@221
   216
      : HIR(node, type)
dvander@195
   217
    {
dvander@195
   218
    }
dvander@195
   219
dvander@195
   220
    // Pushes a reference to the LValue on the stack.
dvander@195
   221
    virtual void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_) = 0;
dvander@215
   222
    
dvander@215
   223
    // Duplicates a stack reference.
dvander@215
   224
    virtual void hold(BytecodeEmitter &emitter_) = 0;
dvander@195
   225
dvander@218
   226
    // Reorders the stack for a post-increment operation:
dvander@218
   227
    //   REF VAL -> VAL REF VAL
dvander@218
   228
    virtual void swapAndPick(BytecodeEmitter &emitter_) = 0;
dvander@218
   229
dvander@195
   230
    // Given a stack layout of the form:
dvander@195
   231
    //  [-1]    value
dvander@195
   232
    //  [-2..n] ref
dvander@195
   233
    //
dvander@195
   234
    // Emits a store to the reference.
dvander@195
   235
    virtual void store(BytecodeEmitter &emitter_) = 0;
dvander@195
   236
    virtual void load(BytecodeEmitter &emitter_) = 0;
dvander@195
   237
dvander@222
   238
    // Try to make a direct reference, if semantics allow it. False if the
dvander@222
   239
    // caller must allocate a reference to the stack.
dvander@222
   240
    virtual bool ref(BytecodeEmitter &emitter_) = 0;
dvander@222
   241
dvander@195
   242
    bool isLValue() const {
dvander@195
   243
        return true;
dvander@195
   244
    }
dvander@195
   245
};
dvander@195
   246
dvander@195
   247
class HLocal : public HLValue
dvander@195
   248
{
dvander@195
   249
  public:
dvander@222
   250
    HLocal(AstNode *node, VariableSymbol *sym);
dvander@195
   251
dvander@195
   252
    DEFINE_HIR(Local);
dvander@195
   253
dvander@195
   254
    // Pushes a reference to the LValue on the stack.
dvander@195
   255
    void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_);
dvander@215
   256
    void hold(BytecodeEmitter &emitter_);
dvander@218
   257
    void swapAndPick(BytecodeEmitter &emitter_);
dvander@195
   258
    void store(BytecodeEmitter &emitter_);
dvander@195
   259
    void load(BytecodeEmitter &emitter_);
dvander@222
   260
    bool ref(BytecodeEmitter &emitter_);
dvander@222
   261
dvander@222
   262
    VariableSymbol *sym() const {
dvander@222
   263
        return sym_;
dvander@222
   264
    }
dvander@195
   265
dvander@195
   266
  private:
dvander@195
   267
    VariableSymbol *sym_;
dvander@195
   268
};
dvander@195
   269
dvander@195
   270
class HIndex : public HLValue
dvander@195
   271
{
dvander@195
   272
  public:
dvander@221
   273
    HIndex(AstNode *node, Type *type, HIR *left, HIR *right)
dvander@221
   274
      : HLValue(node, type),
dvander@195
   275
        left_(left),
dvander@195
   276
        right_(right)
dvander@195
   277
    {
dvander@195
   278
    }
dvander@195
   279
dvander@195
   280
    DEFINE_HIR(Index);
dvander@195
   281
dvander@195
   282
    void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_);
dvander@215
   283
    void hold(BytecodeEmitter &emitter_);
dvander@218
   284
    void swapAndPick(BytecodeEmitter &emitter_);
dvander@195
   285
    void store(BytecodeEmitter &emitter_);
dvander@195
   286
    void load(BytecodeEmitter &emitter_);
dvander@222
   287
    bool ref(BytecodeEmitter &emitter_);
dvander@195
   288
dvander@195
   289
  private:
dvander@195
   290
    HIR *left_;
dvander@195
   291
    HIR *right_;
dvander@195
   292
};
dvander@195
   293
dvander@195
   294
class HGlobal : public HLValue
dvander@195
   295
{
dvander@195
   296
  public:
dvander@221
   297
    HGlobal(AstNode *node, Symbol *sym)
dvander@221
   298
      : HLValue(node, sym->type()),
dvander@195
   299
        sym_(sym)
dvander@195
   300
    {
dvander@195
   301
    }
dvander@195
   302
dvander@195
   303
    DEFINE_HIR(Global);
dvander@195
   304
dvander@195
   305
    void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_);
dvander@215
   306
    void hold(BytecodeEmitter &emitter_);
dvander@218
   307
    void swapAndPick(BytecodeEmitter &emitter_);
dvander@195
   308
    void store(BytecodeEmitter &emitter_);
dvander@195
   309
    void load(BytecodeEmitter &emitter_);
dvander@222
   310
    bool ref(BytecodeEmitter &emitter_);
dvander@195
   311
dvander@195
   312
    Symbol *sym() const {
dvander@195
   313
        return sym_;
dvander@195
   314
    }
dvander@195
   315
dvander@195
   316
  private:
dvander@195
   317
    Symbol *sym_;
dvander@195
   318
};
dvander@195
   319
dvander@195
   320
class HBinary : public HIR
dvander@195
   321
{
dvander@195
   322
  public:
dvander@221
   323
    HBinary(AstNode *node, Type *type, TokenKind token, HIR *left, HIR *right)
dvander@221
   324
      : HIR(node, type),
dvander@195
   325
        token_(token),
dvander@195
   326
        left_(left),
dvander@195
   327
        right_(right)
dvander@195
   328
    {
dvander@195
   329
    }
dvander@195
   330
dvander@195
   331
    DEFINE_HIR(Binary);
dvander@195
   332
    TokenKind token() const {
dvander@195
   333
        return token_;
dvander@195
   334
    }
dvander@195
   335
    HIR *left() const {
dvander@195
   336
        return left_;
dvander@195
   337
    }
dvander@195
   338
    HIR *right() const {
dvander@195
   339
        return right_;
dvander@195
   340
    }
dvander@195
   341
dvander@195
   342
  private:
dvander@195
   343
    TokenKind token_;
dvander@195
   344
    HIR *left_;
dvander@195
   345
    HIR *right_;
dvander@195
   346
};
dvander@195
   347
dvander@195
   348
class HFloat : public HIR
dvander@195
   349
{
dvander@195
   350
  public:
dvander@221
   351
    HFloat(AstNode *node, Type *type, float value)
dvander@221
   352
      : HIR(node, type),
dvander@195
   353
        value_(value)
dvander@195
   354
    {
dvander@195
   355
    }
dvander@195
   356
dvander@195
   357
    DEFINE_HIR(Float);
dvander@195
   358
    float value() const {
dvander@195
   359
        return value_;
dvander@195
   360
    }
dvander@195
   361
dvander@195
   362
  private:
dvander@195
   363
    float value_;
dvander@195
   364
};
dvander@195
   365
dvander@195
   366
class HStore : public HIR
dvander@195
   367
{
dvander@195
   368
  public:
dvander@221
   369
    HStore(AstNode *node, HLValue *lval, HIR *rval)
dvander@221
   370
      : HIR(node, lval->type()),
dvander@215
   371
        kind_(TOK_ASSIGN),
dvander@215
   372
        lval_(lval),
dvander@215
   373
        rval_(rval)
dvander@215
   374
    {
dvander@215
   375
    }
dvander@215
   376
dvander@221
   377
    HStore(AstNode *node, TokenKind kind, HLValue *lval, HIR *rval)
dvander@221
   378
      : HIR(node, lval->type()),
dvander@215
   379
        kind_(kind),
dvander@195
   380
        lval_(lval),
dvander@195
   381
        rval_(rval)
dvander@195
   382
    {
dvander@195
   383
    }
dvander@195
   384
dvander@195
   385
    DEFINE_HIR(Store);
dvander@195
   386
dvander@195
   387
    HLValue *lval() const {
dvander@195
   388
        return lval_;
dvander@195
   389
    }
dvander@195
   390
    HIR *rval() const {
dvander@195
   391
        return rval_;
dvander@195
   392
    }
dvander@215
   393
    TokenKind kind() const {
dvander@215
   394
        return kind_;
dvander@215
   395
    }
dvander@195
   396
dvander@195
   397
  private:
dvander@216
   398
    TokenKind kind_;
dvander@195
   399
    HLValue *lval_;
dvander@195
   400
    HIR *rval_;
dvander@195
   401
};
dvander@195
   402
dvander@218
   403
class HPostIncDec : public HIR
dvander@218
   404
{
dvander@218
   405
  public:
dvander@221
   406
    HPostIncDec(AstNode *node, TokenKind kind, HLValue *lval, HIR *rval)
dvander@221
   407
      : HIR(node, lval->type()),
dvander@218
   408
        kind_(kind),
dvander@218
   409
        lval_(lval),
dvander@218
   410
        rval_(rval)
dvander@218
   411
    {
dvander@218
   412
    }
dvander@218
   413
dvander@218
   414
    DEFINE_HIR(PostIncDec);
dvander@218
   415
dvander@218
   416
    HLValue *lval() const {
dvander@218
   417
        return lval_;
dvander@218
   418
    }
dvander@218
   419
    HIR *rval() const {
dvander@218
   420
        return rval_;
dvander@218
   421
    }
dvander@218
   422
    TokenKind kind() const {
dvander@218
   423
        return kind_;
dvander@218
   424
    }
dvander@218
   425
dvander@218
   426
  private:
dvander@218
   427
    TokenKind kind_;
dvander@218
   428
    HLValue *lval_;
dvander@218
   429
    HIR *rval_;
dvander@218
   430
};
dvander@218
   431
dvander@195
   432
class HCall : public HIR
dvander@195
   433
{
dvander@195
   434
  public:
dvander@221
   435
    HCall(AstNode *node, Type *type, HIR *callee, HIRList *args)
dvander@221
   436
      : HIR(node, type),
dvander@195
   437
        callee_(callee),
dvander@195
   438
        args_(args)
dvander@195
   439
    {
dvander@195
   440
    }
dvander@195
   441
dvander@195
   442
    DEFINE_HIR(Call);
dvander@195
   443
dvander@195
   444
    HIR *callee() const {
dvander@195
   445
        return callee_;
dvander@195
   446
    }
dvander@195
   447
    HIRList *args() const {
dvander@195
   448
        return args_;
dvander@195
   449
    }
dvander@195
   450
dvander@195
   451
  private:
dvander@195
   452
    HIR *callee_;
dvander@195
   453
    HIRList *args_;
dvander@195
   454
};
dvander@195
   455
dvander@222
   456
class HToRef : public HIR
dvander@222
   457
{
dvander@222
   458
  public:
dvander@222
   459
    HToRef(AstNode *node, Type *type, HIR *in)
dvander@222
   460
      : HIR(node, type),
dvander@222
   461
        in_(in)
dvander@222
   462
    {
dvander@222
   463
    }
dvander@222
   464
dvander@222
   465
    DEFINE_HIR(ToRef);
dvander@222
   466
dvander@222
   467
    HIR *in() const {
dvander@222
   468
        return in_;
dvander@222
   469
    }
dvander@222
   470
dvander@222
   471
  private:
dvander@222
   472
    HIR *in_;
dvander@222
   473
};
dvander@222
   474
dvander@195
   475
#undef DEFINE_HIR
dvander@195
   476
dvander@195
   477
void EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir);
dvander@195
   478
dvander@195
   479
}
dvander@195
   480
dvander@195
   481
#endif // _include_sp2_hir_h_