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