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