Re-add postinc support.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
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)
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.
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/.
20 #include "BytecodeEmitter.h"
21 #include "../Heap-inl.h"
22 #include "../Handles-inl.h"
26 class HIRTranslator : public HIRVisitor
29 HIRTranslator(Zone *zone, BytecodeEmitter &emitter)
35 void translate(HIR *hir) {
39 void visitFloat(HFloat *hir);
40 void visitInteger(HInteger *hir);
41 void visitCall(HCall *call);
42 void visitStore(HStore *store);
43 void visitBinary(HBinary *binary);
44 void visitLocal(HLocal *local);
45 void visitGlobal(HGlobal *global);
46 void visitConvert(HConvert *convert);
47 void visitIndex(HIndex *index);
48 void visitPostIncDec(HPostIncDec *hir);
52 BytecodeEmitter &emitter_;
58 HIRTranslator::visitFloat(HFloat *hir)
60 __ float_(hir->value());
64 HIRTranslator::visitInteger(HInteger *hir)
66 __ int_(hir->value());
70 HIRTranslator::visitCall(HCall *call)
72 Local<FunctionType> fun(zone_, FunctionType::cast(call->callee()->type()));
74 assert(call->args()->length() == fun->parameters()->length());
76 unsigned argc = call->args()->length();
78 for (size_t i = call->args()->length() - 1; i < call->args()->length(); i--) {
79 HIR *hir = call->args()->at(i);
83 call->callee()->accept(this);
88 HGlobal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
93 HGlobal::hold(BytecodeEmitter &emitter_)
98 HGlobal::swapAndPick(BytecodeEmitter &emitter_)
104 HGlobal::store(BytecodeEmitter &emitter_)
110 HGlobal::load(BytecodeEmitter &emitter_)
116 HLocal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
118 if (sym_->type()->isReference())
123 HLocal::hold(BytecodeEmitter &emitter_)
125 if (sym_->type()->isReference())
130 HLocal::swapAndPick(BytecodeEmitter &emitter_)
132 if (sym_->type()->isReference()) {
141 HLocal::store(BytecodeEmitter &emitter_)
143 if (sym_->type()->isReference())
144 __ setref(sym_->type()->contained_ref());
150 HLocal::load(BytecodeEmitter &emitter_)
152 if (sym_->type()->isReference())
153 __ getref(sym_->type());
159 HIndex::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
161 left_->accept(visitor);
162 right_->accept(visitor);
166 HIndex::hold(BytecodeEmitter &emitter_)
172 HIndex::swapAndPick(BytecodeEmitter &emitter_)
175 __ roll3(); // INDEX VALUE BASE
176 __ roll3(); // VALUE BASE INDEX
177 __ pick3(); // VALUE BASE INDEX VALUE
181 HIndex::store(BytecodeEmitter &emitter_)
187 HIndex::load(BytecodeEmitter &emitter_)
193 HIRTranslator::visitLocal(HLocal *local)
195 local->bind(this, emitter_);
196 local->load(emitter_);
200 HIRTranslator::visitIndex(HIndex *index)
202 index->bind(this, emitter_);
203 index->load(emitter_);
207 HIRTranslator::visitGlobal(HGlobal *global)
209 __ getglobal(global->sym());
213 TokenToOpcode(TokenKind kind)
237 case TOK_ASSIGN_USHR:
243 case TOK_ASSIGN_BITAND:
246 case TOK_ASSIGN_BITOR:
261 assert(kind == TOK_BITXOR);
267 HIRTranslator::visitStore(HStore *store)
269 store->lval()->bind(this, emitter_);
270 if (store->kind() == TOK_ASSIGN) {
271 store->rval()->accept(this);
273 // Advanced case: dup the ref, load, op, store.
274 store->lval()->hold(emitter_);
275 store->lval()->load(emitter_);
276 store->rval()->accept(this);
277 __ binary(TokenToOpcode(store->kind()));
279 store->lval()->store(emitter_);
283 HIRTranslator::visitPostIncDec(HPostIncDec *hir)
285 hir->lval()->bind(this, emitter_);
286 hir->lval()->hold(emitter_);
287 hir->lval()->load(emitter_);
288 hir->lval()->swapAndPick(emitter_);
289 hir->rval()->accept(this);
290 __ binary(TokenToOpcode(hir->kind()));
291 hir->lval()->store(emitter_);
296 HIRTranslator::visitBinary(HBinary *binary)
298 binary->left()->accept(this);
299 binary->right()->accept(this);
301 // We define three sets of math operators:
303 // (1) ADD, SUB, MUL, DIV, MOD, which take two equal types and produce
305 // (2) LT, LE, GE, GT, EQ, NE, which take two equal types and produce
307 // (3) SHL, SR, USHR, BITAND, BITOR, BITXOR, BITNOT, which take two
308 // equal integer types and return that integer type.
310 Opcode op = TokenToOpcode(binary->token());
312 if (op >= OP_ADD && op <= OP_NE) {
313 if (binary->type()->isFloat())
314 op = Opcode(int(op) + int(OP_ADD_F - OP_ADD));
316 assert(binary->type()->isInt32());
323 HIRTranslator::visitConvert(HConvert *convert)
325 convert->in()->accept(this);
326 __ unary(convert->opcode());
330 ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
332 HIRTranslator translator(zone, emitter);
333 translator.translate(hir);