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