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