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