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