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