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