src/compiler/HIR.cpp
author David Anderson <dvander@alliedmods.net>
Thu Dec 27 20:44:50 2012 -0800 (2012-12-27)
changeset 245 9371f058625a
parent 236 072f1114ea5d
child 246 f9c4371d59d4
permissions -rw-r--r--
Support admin.inc again.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include "AST.h"
    20 #include "HIR.h"
    21 #include "BytecodeEmitter.h"
    22 #include "../Strings.h"
    23 #include "../Heap-inl.h"
    24 #include "../Handles-inl.h"
    25 
    26 using namespace ke;
    27 
    28 class HIRTranslator : public HIRVisitor
    29 {
    30   public:
    31     HIRTranslator(Zone *zone, BytecodeEmitter &emitter)
    32       : zone_(zone),
    33         emitter_(emitter)
    34     {
    35     }
    36 
    37     void translate(HIR *hir) {
    38         hir->accept(this);
    39     }
    40 
    41     void visitBoolean(HBoolean *hir);
    42     void visitFloat(HFloat *hir);
    43     void visitInteger(HInteger *hir);
    44     void visitArray(HArray *hir);
    45     void visitCall(HCall *call);
    46     void visitStore(HStore *store);
    47     void visitBinary(HBinary *binary);
    48     void visitLocal(HLocal *local);
    49     void visitGlobal(HGlobal *global);
    50     void visitConvert(HConvert *convert);
    51     void visitIndex(HIndex *index);
    52     void visitPostIncDec(HPostIncDec *hir);
    53     void visitToRef(HToRef *hir);
    54 
    55   private:
    56     Zone *zone_;
    57     BytecodeEmitter &emitter_;
    58 };
    59 
    60 #define __ emitter_.
    61 
    62 void
    63 HIRTranslator::visitBoolean(HBoolean *hir)
    64 {
    65     if (hir->value())
    66         __ true_();
    67     else
    68         __ false_();
    69 }
    70 
    71 void
    72 HIRTranslator::visitFloat(HFloat *hir)
    73 {
    74     __ float_(hir->value());
    75 }
    76 
    77 void
    78 HIRTranslator::visitInteger(HInteger *hir)
    79 {
    80     __ int_(hir->value());
    81 }
    82 
    83 void
    84 HIRTranslator::visitArray(HArray *hir)
    85 {
    86     __ object(hir->array());
    87 
    88     if (hir->duplicate())
    89         __ duparray(); 
    90 }
    91 
    92 void
    93 HIRTranslator::visitCall(HCall *call)
    94 {
    95     Local<FunctionType> fun(zone_, FunctionType::cast(call->callee()->type()));
    96     
    97     assert(call->args()->length() == fun->parameters()->length());
    98 
    99     __ note_position(call->node()->pos());
   100 
   101     unsigned argc = call->args()->length();
   102     for (size_t i = call->args()->length() - 1; i < call->args()->length(); i--) {
   103         HIR *hir = call->args()->at(i);
   104         hir->accept(this);
   105     }
   106 
   107     call->callee()->accept(this);
   108     __ call(fun, argc);
   109 }
   110 
   111 void
   112 HGlobal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
   113 {
   114 }
   115 
   116 void
   117 HGlobal::hold(BytecodeEmitter &emitter_)
   118 {
   119 }
   120 
   121 void
   122 HGlobal::swapAndPick(BytecodeEmitter &emitter_)
   123 {
   124     __ dup();
   125 }
   126 
   127 void
   128 HGlobal::store(BytecodeEmitter &emitter_)
   129 {
   130     __ setglobal(sym_);
   131 }
   132 
   133 void
   134 HGlobal::load(BytecodeEmitter &emitter_)
   135 {
   136     __ getglobal(sym_);
   137 }
   138 
   139 bool
   140 HGlobal::ref(BytecodeEmitter &emitter_)
   141 {
   142     return false;
   143 }
   144 
   145 static inline Type *
   146 MaybeDereference(Type *type)
   147 {
   148     if (type->isReference())
   149         return ReferenceType::cast(type)->contained();
   150     return type;
   151 }
   152 
   153 HLocal::HLocal(AstNode *node, VariableSymbol *sym)
   154   : HLValue(node, MaybeDereference(sym->type())),
   155     sym_(sym)
   156 {
   157 }
   158 
   159 void
   160 HLocal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
   161 {
   162     if (sym_->type()->isReference()) {
   163         if (sym_->storage() == VariableSymbol::Local)
   164             __ getlocal(sym_);
   165         else if (sym_->storage() == VariableSymbol::Arg)
   166             __ getarg(sym_);
   167         else
   168             assert(false);
   169     }
   170 }
   171 
   172 void
   173 HLocal::hold(BytecodeEmitter &emitter_)
   174 {
   175     if (sym_->type()->isReference())
   176         __ dup();
   177 }
   178 
   179 void
   180 HLocal::swapAndPick(BytecodeEmitter &emitter_)
   181 {
   182     if (sym_->type()->isReference()) {
   183         __ swap();
   184         __ pick2();
   185     } else {
   186         __ dup();
   187     }
   188 }
   189 
   190 void
   191 HLocal::store(BytecodeEmitter &emitter_)
   192 {
   193     if (sym_->type()->isReference()) {
   194         __ setref(ReferenceType::cast(sym_->type())->contained());
   195     } else {
   196         if (sym_->storage() == VariableSymbol::Local)
   197             __ setlocal(sym_);
   198         else if (sym_->storage() == VariableSymbol::Arg)
   199             __ setarg(sym_);
   200         else
   201             assert(false);
   202     }
   203 }
   204 
   205 void
   206 HLocal::load(BytecodeEmitter &emitter_)
   207 {
   208     if (sym_->type()->isReference())
   209         __ getref(ReferenceType::cast(sym_->type())->contained());
   210     else if (sym_->storage() == VariableSymbol::Local)
   211         __ getlocal(sym_);
   212     else if (sym_->storage() == VariableSymbol::Arg)
   213         __ getarg(sym_);
   214     else
   215         assert(false);
   216 }
   217 
   218 bool
   219 HLocal::ref(BytecodeEmitter &emitter_)
   220 {
   221     if (sym_->storage() == VariableSymbol::Heap) {
   222         // Closing over a reference should never pass SemA.
   223         assert(!sym_->type()->isReference());
   224 
   225         // We don't support direct references to heap-allocated locals. This
   226         // should probably be banned in SemA? But for now, just assert. :TODO:
   227         assert(false);
   228         return false;
   229     }
   230         
   231     if (sym_->type()->isReference()) {
   232         if (sym_->storage() == VariableSymbol::Local)
   233             __ getlocal(sym_);
   234         else if (sym_->storage() == VariableSymbol::Arg)
   235             __ getarg(sym_);
   236         else
   237             assert(false);
   238     } else {
   239         __ newref(sym_);
   240     }
   241 
   242     return true;
   243 }
   244 
   245 void
   246 HIndex::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
   247 {
   248     __ note_position(node()->pos());
   249     left_->accept(visitor);
   250     right_->accept(visitor);
   251 }
   252 
   253 void
   254 HIndex::hold(BytecodeEmitter &emitter_)
   255 {
   256     __ dup2();
   257 }
   258 
   259 void
   260 HIndex::swapAndPick(BytecodeEmitter &emitter_)
   261 {
   262     // BASE INDEX VALUE
   263     __ roll3();         // INDEX VALUE BASE
   264     __ roll3();         // VALUE BASE INDEX
   265     __ pick3();         // VALUE BASE INDEX VALUE
   266 }
   267 
   268 void
   269 HIndex::store(BytecodeEmitter &emitter_)
   270 {
   271     __ setelem(type());
   272 }
   273 
   274 void
   275 HIndex::load(BytecodeEmitter &emitter_)
   276 {
   277     __ getelem(type());
   278 }
   279 
   280 bool
   281 HIndex::ref(BytecodeEmitter &emitter_)
   282 {
   283     return false;
   284 }
   285 
   286 void
   287 HIRTranslator::visitLocal(HLocal *local)
   288 {
   289     local->bind(this, emitter_);
   290     local->load(emitter_);
   291 }
   292 
   293 void
   294 HIRTranslator::visitIndex(HIndex *index)
   295 {
   296     index->bind(this, emitter_);
   297     index->load(emitter_);
   298 }
   299 
   300 void
   301 HIRTranslator::visitGlobal(HGlobal *global)
   302 {
   303     global->bind(this, emitter_);
   304     global->load(emitter_);
   305 }
   306 
   307 static inline Opcode
   308 TokenToOpcode(TokenKind kind)
   309 {
   310     switch (kind) {
   311       case TOK_PLUS:
   312       case TOK_ASSIGN_ADD:
   313       case TOK_INCREMENT:
   314         return OP_ADD;
   315       case TOK_MINUS:
   316       case TOK_ASSIGN_SUB:
   317       case TOK_DECREMENT:
   318         return OP_SUB;
   319       case TOK_STAR:
   320       case TOK_ASSIGN_MUL:
   321         return OP_MUL;
   322       case TOK_SLASH:
   323       case TOK_ASSIGN_DIV:
   324         return OP_DIV;
   325       case TOK_PERCENT:
   326       case TOK_ASSIGN_MOD:
   327         return OP_MOD;
   328       case TOK_SHR:
   329       case TOK_ASSIGN_SHR:
   330         return OP_SHR;
   331       case TOK_USHR:
   332       case TOK_ASSIGN_USHR:
   333         return OP_USHR;
   334       case TOK_SHL:
   335       case TOK_ASSIGN_SHL:
   336         return OP_SHL;
   337       case TOK_BITAND:
   338       case TOK_ASSIGN_BITAND:
   339         return OP_BITAND;
   340       case TOK_BITOR:
   341       case TOK_ASSIGN_BITOR:
   342         return OP_BITOR;
   343       case TOK_GT:
   344           return OP_GT;
   345       case TOK_GE:
   346           return OP_GE;
   347       case TOK_LT:
   348           return OP_LT;
   349       case TOK_LE:
   350           return OP_LE;
   351       case TOK_EQUALS:
   352           return OP_EQ;
   353       case TOK_NOTEQUALS:
   354           return OP_NE;
   355       default:
   356         assert(kind == TOK_BITXOR);
   357         return OP_BITXOR;
   358     }
   359 }
   360 
   361 void
   362 HIRTranslator::visitStore(HStore *store)
   363 {
   364     store->lval()->bind(this, emitter_);
   365 
   366     if (store->kind() == TOK_ASSIGN) {
   367         // Fixed-length arrays and structs have copy semantics.
   368         Local<Type> type(zone_, store->lval()->type());
   369         if (type->isArray() && ArrayType::cast(type)->isFixedLength()) {
   370             store->lval()->load(emitter_);
   371             store->rval()->accept(this);
   372             __ copyarray();
   373         } else if (type->isStruct()) {
   374             store->lval()->load(emitter_);
   375             store->rval()->accept(this);
   376             __ copystruct();
   377         } else {
   378             store->rval()->accept(this);
   379             store->lval()->store(emitter_);
   380         }
   381     } else {
   382         // Advanced case: dup the ref, load, op, store.
   383         store->lval()->hold(emitter_);
   384         store->lval()->load(emitter_);
   385         store->rval()->accept(this);
   386         __ binary(TokenToOpcode(store->kind()));
   387         store->lval()->store(emitter_);
   388     }
   389 }
   390 
   391 void
   392 HIRTranslator::visitPostIncDec(HPostIncDec *hir)
   393 {
   394     hir->lval()->bind(this, emitter_);
   395     hir->lval()->hold(emitter_);
   396     hir->lval()->load(emitter_);
   397     hir->lval()->swapAndPick(emitter_);
   398     hir->rval()->accept(this);
   399     __ binary(TokenToOpcode(hir->kind()));
   400     hir->lval()->store(emitter_);
   401     __ pop();
   402 }
   403 
   404 void
   405 HIRTranslator::visitBinary(HBinary *binary)
   406 {
   407     binary->left()->accept(this);
   408     binary->right()->accept(this);
   409 
   410     // We define three sets of math operators:
   411     //
   412     //  (1) ADD, SUB, MUL, DIV, MOD, which take two equal types and produce
   413     //      the same type.
   414     //  (2) LT, LE, GE, GT, EQ, NE, which take two equal types and produce
   415     //      a boolean.
   416     //  (3) SHL, SR, USHR, BITAND, BITOR, BITXOR, BITNOT, which take two
   417     //      equal integer types and return that integer type.
   418     //
   419     Opcode op = TokenToOpcode(binary->token());
   420 
   421     if (op == OP_DIV)
   422         __ note_position(binary->node()->pos());
   423 
   424     if (op >= OP_ADD && op <= OP_NE) {
   425         if (binary->type()->isFloat())
   426             op = Opcode(int(op) + int(OP_ADD_F - OP_ADD));
   427     } else {
   428         assert(binary->type()->isInt32());
   429     }
   430 
   431     __ binary(op);
   432 }
   433 
   434 void
   435 HIRTranslator::visitConvert(HConvert *convert)
   436 {
   437     convert->in()->accept(this);
   438     __ unary(convert->opcode());
   439 }
   440 
   441 void
   442 HIRTranslator::visitToRef(HToRef *hir)
   443 {
   444     HIR *in = hir->in();
   445 
   446     // See if we can bind a direct reference.
   447     if (in->isLValue() && in->toLValue()->ref(emitter_))
   448         return;
   449 
   450     // No, we can't. So instead we create an on-stack reference.
   451     in->accept(this);
   452     __ slotref_lifo();
   453 }
   454 
   455 void
   456 ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
   457 {
   458     HIRTranslator translator(zone, emitter);
   459     translator.translate(hir);
   460 }