Get string literals working again.
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 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);
56 BytecodeEmitter &emitter_;
62 HIRTranslator::visitFloat(HFloat *hir)
64 __ float_(hir->value());
68 HIRTranslator::visitInteger(HInteger *hir)
70 __ int_(hir->value());
74 HIRTranslator::visitArray(HArray *hir)
76 __ object(hir->array());
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.
86 HIRTranslator::visitCall(HCall *call)
88 Local<FunctionType> fun(zone_, FunctionType::cast(call->callee()->type()));
90 assert(call->args()->length() == fun->parameters()->length());
92 __ note_position(call->node()->pos());
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);
100 call->callee()->accept(this);
105 HGlobal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
110 HGlobal::hold(BytecodeEmitter &emitter_)
115 HGlobal::swapAndPick(BytecodeEmitter &emitter_)
121 HGlobal::store(BytecodeEmitter &emitter_)
127 HGlobal::load(BytecodeEmitter &emitter_)
133 HGlobal::ref(BytecodeEmitter &emitter_)
139 MaybeDereference(Type *type)
141 if (type->isReference())
142 return ReferenceType::cast(type)->contained();
146 HLocal::HLocal(AstNode *node, VariableSymbol *sym)
147 : HLValue(node, MaybeDereference(sym->type())),
153 HLocal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
155 if (sym_->type()->isReference()) {
156 if (sym_->storage() == VariableSymbol::Local)
158 else if (sym_->storage() == VariableSymbol::Arg)
166 HLocal::hold(BytecodeEmitter &emitter_)
168 if (sym_->type()->isReference())
173 HLocal::swapAndPick(BytecodeEmitter &emitter_)
175 if (sym_->type()->isReference()) {
184 HLocal::store(BytecodeEmitter &emitter_)
186 if (sym_->type()->isReference()) {
187 __ setref(ReferenceType::cast(sym_->type())->contained());
189 if (sym_->storage() == VariableSymbol::Local)
191 else if (sym_->storage() == VariableSymbol::Arg)
199 HLocal::load(BytecodeEmitter &emitter_)
201 if (sym_->type()->isReference())
202 __ getref(ReferenceType::cast(sym_->type())->contained());
203 else if (sym_->storage() == VariableSymbol::Local)
205 else if (sym_->storage() == VariableSymbol::Arg)
212 HLocal::ref(BytecodeEmitter &emitter_)
214 if (sym_->storage() == VariableSymbol::Heap) {
215 // Closing over a reference should never pass SemA.
216 assert(!sym_->type()->isReference());
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:
224 if (sym_->type()->isReference()) {
225 if (sym_->storage() == VariableSymbol::Local)
227 else if (sym_->storage() == VariableSymbol::Arg)
239 HIndex::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
241 __ note_position(node()->pos());
242 left_->accept(visitor);
243 right_->accept(visitor);
247 HIndex::hold(BytecodeEmitter &emitter_)
253 HIndex::swapAndPick(BytecodeEmitter &emitter_)
256 __ roll3(); // INDEX VALUE BASE
257 __ roll3(); // VALUE BASE INDEX
258 __ pick3(); // VALUE BASE INDEX VALUE
262 HIndex::store(BytecodeEmitter &emitter_)
268 HIndex::load(BytecodeEmitter &emitter_)
274 HIndex::ref(BytecodeEmitter &emitter_)
280 HIRTranslator::visitLocal(HLocal *local)
282 local->bind(this, emitter_);
283 local->load(emitter_);
287 HIRTranslator::visitIndex(HIndex *index)
289 index->bind(this, emitter_);
290 index->load(emitter_);
294 HIRTranslator::visitGlobal(HGlobal *global)
296 global->bind(this, emitter_);
297 global->load(emitter_);
301 TokenToOpcode(TokenKind kind)
325 case TOK_ASSIGN_USHR:
331 case TOK_ASSIGN_BITAND:
334 case TOK_ASSIGN_BITOR:
349 assert(kind == TOK_BITXOR);
355 HIRTranslator::visitStore(HStore *store)
357 store->lval()->bind(this, emitter_);
358 if (store->kind() == TOK_ASSIGN) {
359 store->rval()->accept(this);
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()));
367 store->lval()->store(emitter_);
371 HIRTranslator::visitPostIncDec(HPostIncDec *hir)
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_);
384 HIRTranslator::visitBinary(HBinary *binary)
386 binary->left()->accept(this);
387 binary->right()->accept(this);
389 // We define three sets of math operators:
391 // (1) ADD, SUB, MUL, DIV, MOD, which take two equal types and produce
393 // (2) LT, LE, GE, GT, EQ, NE, which take two equal types and produce
395 // (3) SHL, SR, USHR, BITAND, BITOR, BITXOR, BITNOT, which take two
396 // equal integer types and return that integer type.
398 Opcode op = TokenToOpcode(binary->token());
401 __ note_position(binary->node()->pos());
403 if (op >= OP_ADD && op <= OP_NE) {
404 if (binary->type()->isFloat())
405 op = Opcode(int(op) + int(OP_ADD_F - OP_ADD));
407 assert(binary->type()->isInt32());
414 HIRTranslator::visitConvert(HConvert *convert)
416 convert->in()->accept(this);
417 __ unary(convert->opcode());
421 HIRTranslator::visitToRef(HToRef *hir)
425 // See if we can bind a direct reference.
426 if (in->isLValue() && in->toLValue()->ref(emitter_))
429 // No, we can't. So instead we create an on-stack reference.
435 ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
437 HIRTranslator translator(zone, emitter);
438 translator.translate(hir);