1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
/* $Id$
*
* Generate intermediate code, loop specific parts.
*
* Copyright (C) 2008-2009 FAUmachine Team <info@faumachine.org>.
* This program is free software. You can redistribute it and/or modify it
* under the terms of the GNU General Public License, either version 2 of
* the License, or (at your option) any later version. See COPYING.
*/
#include "frontend/visitor/GCLoops.hpp"
#include "intermediate/opcodes/Jmp.hpp"
#include "intermediate/opcodes/Jbe.hpp"
#include "intermediate/opcodes/Jb.hpp"
#include "intermediate/opcodes/Mov.hpp"
#include "intermediate/opcodes/Add.hpp"
#include "intermediate/opcodes/Sub.hpp"
#include "intermediate/operands/ImmediateOperand.hpp"
#include "intermediate/operands/RegisterFactory.hpp"
#include "intermediate/container/LabelFactory.hpp"
namespace ast {
using namespace intermediate;
/*
* ===================== WHILE ITERATE ========================
*/
WhileIterate::WhileIterate(
CodeContainer &container
) : cc(container),
loopInc(LabelFactory::getLabel("while_iter_inc")),
loopDone(LabelFactory::getLabel("while_iter_done")),
loopCheck(LabelFactory::getLabel("while_iter_check"))
{
}
WhileIterate::~WhileIterate()
{
}
void
WhileIterate::addIteration(void)
{
this->genIterateCode();
}
void
WhileIterate::genIterateCode(void)
{
this->initializeCounter();
this->cc.addCode(loopCheck);
this->checkCondition();
this->loopBody();
this->cc.addCode(loopInc);
this->incCounter();
Jmp *jmp = new Jmp(this->loopCheck);
this->cc.addCode(jmp);
this->cc.addCode(loopDone);
}
/*
* ===================== FOR LOOP ITERATE =====================
*/
void
ForLoopIterate::initializeCounter(void)
{
Mov *mov = new Mov(&this->init, &this->cnt);
this->cc.addCode(mov);
}
void
ForLoopIterate::checkCondition(void)
{
// FIXME this won't work if rbound is equal to one of the bounds
// of the underlying integer type (endless loop).
//
// The following construct would be one possible solution:
//
// counter = init;
// if (init > bound) goto out;
// while (true) {
// loopBody();
// if init == bound goto out;
// loopInc();
// }
// out:
Node *goOut;
if (this->isAsc) {
goOut = new Jb(&this->rbound, &this->cnt, this->loopDone);
} else {
goOut = new Jb(&this->cnt, &this->rbound, this->loopDone);
}
this->cc.addCode(goOut);
}
void
ForLoopIterate::incCounter(void)
{
Register *tmp = this->cc.createRegister(OP_TYPE_INTEGER);
Node *inc;
if (this->isAsc) {
inc = new Add(&this->cnt, ImmediateOperand::getOne(), tmp);
} else {
inc = new Sub(&this->cnt, ImmediateOperand::getOne(), tmp);
}
Mov *mov = new Mov(tmp, &this->cnt);
this->cc.addCode(inc);
this->cc.addCode(mov);
}
}; /* namespace ast */
|