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