Normalise line endings.
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/.
21 #include "BytecodeEmitter.h"
22 #include "../Strings.h"
23 #include "../Heap-inl.h"
24 #include "../Handles-inl.h"
28 class HIRTranslator : public HIRVisitor
31 HIRTranslator(Zone *zone, BytecodeEmitter &emitter)
37 void translate(HIR *hir) {
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 visitField(HField *field);
54 void visitPostIncDec(HPostIncDec *hir);
55 void visitToRef(HToRef *hir);
56 void visitNewDependentArray(HNewDependentArray *hir);
57 void visitImport(HImport *import);
61 BytecodeEmitter &emitter_;
67 HIRTranslator::visitBoolean(HBoolean *hir)
76 HIRTranslator::visitFloat(HFloat *hir)
78 __ float_(hir->value());
82 HIRTranslator::visitInteger(HInteger *hir)
84 __ int_(hir->value());
88 HIRTranslator::visitArray(HArray *hir)
90 __ object(hir->array());
97 HIRTranslator::visitCall(HCall *call)
99 Local<FunctionType> fun(zone_, FunctionType::cast(call->callee()->type()));
101 assert(call->args()->length() == fun->parameters()->length());
103 __ note_position(call->node()->pos());
105 unsigned argc = call->args()->length();
106 for (size_t i = call->args()->length() - 1; i < call->args()->length(); i--) {
107 HIR *hir = call->args()->at(i);
111 call->callee()->accept(this);
116 HGlobal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
121 HGlobal::hold(BytecodeEmitter &emitter_)
126 HGlobal::swapAndPick(BytecodeEmitter &emitter_)
132 HGlobal::store(BytecodeEmitter &emitter_)
138 HGlobal::load(BytecodeEmitter &emitter_)
144 HGlobal::ref(BytecodeEmitter &emitter_)
150 MaybeDereference(Type *type)
152 if (type->isReference())
153 return ReferenceType::cast(type)->contained();
157 HLocal::HLocal(AstNode *node, VariableSymbol *sym)
158 : HLValue(node, MaybeDereference(sym->type())),
164 HLocal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
166 if (sym_->type()->isReference()) {
167 if (sym_->storage() == VariableSymbol::Local)
169 else if (sym_->storage() == VariableSymbol::Arg)
177 HLocal::hold(BytecodeEmitter &emitter_)
179 if (sym_->type()->isReference())
184 HLocal::swapAndPick(BytecodeEmitter &emitter_)
186 if (sym_->type()->isReference()) {
195 HLocal::store(BytecodeEmitter &emitter_)
197 if (sym_->type()->isReference()) {
198 __ setref(ReferenceType::cast(sym_->type())->contained());
200 if (sym_->storage() == VariableSymbol::Local)
202 else if (sym_->storage() == VariableSymbol::Arg)
210 HLocal::load(BytecodeEmitter &emitter_)
212 if (sym_->type()->isReference())
213 __ getref(ReferenceType::cast(sym_->type())->contained());
214 else if (sym_->storage() == VariableSymbol::Local)
216 else if (sym_->storage() == VariableSymbol::Arg)
223 HLocal::ref(BytecodeEmitter &emitter_)
225 if (sym_->storage() == VariableSymbol::Heap) {
226 // Closing over a reference should never pass SemA.
227 assert(!sym_->type()->isReference());
229 // We don't support direct references to heap-allocated locals. This
230 // should probably be banned in SemA? But for now, just assert. :TODO:
235 if (sym_->type()->isReference()) {
236 if (sym_->storage() == VariableSymbol::Local)
238 else if (sym_->storage() == VariableSymbol::Arg)
250 HIndex::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
252 __ note_position(node()->pos());
253 left_->accept(visitor);
254 right_->accept(visitor);
258 HIndex::hold(BytecodeEmitter &emitter_)
264 HIndex::swapAndPick(BytecodeEmitter &emitter_)
267 __ roll3(); // INDEX VALUE BASE
268 __ roll3(); // VALUE BASE INDEX
269 __ pick3(); // VALUE BASE INDEX VALUE
273 HIndex::store(BytecodeEmitter &emitter_)
279 HIndex::load(BytecodeEmitter &emitter_)
285 HIndex::ref(BytecodeEmitter &emitter_)
291 HField::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
293 __ note_position(node()->pos());
294 base_->accept(visitor);
298 HField::hold(BytecodeEmitter &emitter_)
304 HField::swapAndPick(BytecodeEmitter &emitter_)
307 __ swap(); // VALUE BASE
308 __ pick2(); // VALUE BASE VALUE
312 HField::store(BytecodeEmitter &emitter_)
314 __ setfield(index_, type());
318 HField::load(BytecodeEmitter &emitter_)
320 __ getfield(index_, type());
324 HField::ref(BytecodeEmitter &emitter_)
330 HIRTranslator::visitLocal(HLocal *local)
332 local->bind(this, emitter_);
333 local->load(emitter_);
337 HIRTranslator::visitIndex(HIndex *index)
339 index->bind(this, emitter_);
340 index->load(emitter_);
344 HIRTranslator::visitField(HField *field)
346 field->bind(this, emitter_);
347 field->load(emitter_);
351 HIRTranslator::visitGlobal(HGlobal *global)
353 global->bind(this, emitter_);
354 global->load(emitter_);
358 TokenToOpcode(TokenKind kind)
382 case TOK_ASSIGN_USHR:
388 case TOK_ASSIGN_BITAND:
391 case TOK_ASSIGN_BITOR:
406 assert(kind == TOK_BITXOR);
412 HIRTranslator::visitStore(HStore *store)
414 store->lval()->bind(this, emitter_);
416 if (store->kind() == TOK_ASSIGN) {
417 // Fixed-length arrays and structs have copy semantics.
418 Local<Type> type(zone_, store->lval()->type());
419 if (type->isArray() && ArrayType::cast(type)->isFixedLength()) {
420 store->lval()->load(emitter_);
421 store->rval()->accept(this);
423 } else if (type->isStruct()) {
424 store->lval()->load(emitter_);
425 store->rval()->accept(this);
428 store->rval()->accept(this);
429 store->lval()->store(emitter_);
432 // Advanced case: dup the ref, load, op, store.
433 store->lval()->hold(emitter_);
434 store->lval()->load(emitter_);
435 store->rval()->accept(this);
436 __ binary(TokenToOpcode(store->kind()));
437 store->lval()->store(emitter_);
442 HIRTranslator::visitPostIncDec(HPostIncDec *hir)
444 hir->lval()->bind(this, emitter_);
445 hir->lval()->hold(emitter_);
446 hir->lval()->load(emitter_);
447 hir->lval()->swapAndPick(emitter_);
448 hir->rval()->accept(this);
449 __ binary(TokenToOpcode(hir->kind()));
450 hir->lval()->store(emitter_);
455 HIRTranslator::visitBinary(HBinary *binary)
457 binary->left()->accept(this);
458 binary->right()->accept(this);
460 // We define three sets of math operators:
462 // (1) ADD, SUB, MUL, DIV, MOD, which take two equal types and produce
464 // (2) LT, LE, GE, GT, EQ, NE, which take two equal types and produce
466 // (3) SHL, SR, USHR, BITAND, BITOR, BITXOR, BITNOT, which take two
467 // equal integer types and return that integer type.
469 Opcode op = TokenToOpcode(binary->token());
472 __ note_position(binary->node()->pos());
474 if (op >= OP_ADD && op <= OP_NE) {
475 if (binary->type()->isFloat())
476 op = Opcode(int(op) + int(OP_ADD_F - OP_ADD));
478 assert(binary->type()->isInt32());
485 HIRTranslator::visitUnary(HUnary *unary)
487 unary->in()->accept(this);
489 switch (unary->token()) {
495 if (unary->type()->isFloat())
502 assert(unary->token() == TOK_LABEL);
503 __ bitcast(unary->type());
509 HIRTranslator::visitConvert(HConvert *convert)
511 convert->in()->accept(this);
512 __ unary(convert->opcode());
516 HIRTranslator::visitToRef(HToRef *hir)
520 // See if we can bind a direct reference.
521 if (in->isLValue() && in->toLValue()->ref(emitter_))
524 // No, we can't. So instead we create an on-stack reference.
530 HIRTranslator::visitNewDependentArray(HNewDependentArray *hir)
532 hir->base()->accept(this);
533 hir->index()->accept(this);
535 Local<ArrayType> type(zone_, ArrayType::cast(hir->type()));
537 // The dependent map is used for the opcode, but is not attached.
538 Local<ArrayMap> map(zone_, ArrayMap::NewDependent(zone_, type));
546 HIRTranslator::visitImport(HImport *import)
548 __ import(import->index());
552 ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
554 HIRTranslator translator(zone, emitter);
555 translator.translate(hir);