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