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