Logo Search packages:      
Sourcecode: fauhdlc version File versions

GCBuiltins.cpp

/* $Id: GCBuiltins.cpp 4323 2009-01-27 13:48:12Z potyra $ 
 *
 * Generate intermediate code, intermediate code implementation of builtins.
 *
 * 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/GCBuiltins.hpp"
#include <cassert>
#include "frontend/ast/AssociationElement.hpp"
#include "frontend/misc/BuiltinSymbolTable.hpp"
#include "intermediate/container/LabelFactory.hpp"
#include "intermediate/operands/ImmediateOperand.hpp"
#include "intermediate/opcodes/Mov.hpp"
#include "intermediate/opcodes/Je.hpp"
#include "intermediate/opcodes/Jne.hpp"
#include "intermediate/opcodes/Jb.hpp"
#include "intermediate/opcodes/Jbe.hpp"

namespace ast {

using namespace intermediate;

RegisterSet
00028 GCBuiltinsNoShortCircuit::emitCode(
      GenCode &gc, 
      std::list<AssociationElement*> ops
) const
{
      std::list<RegisterSet> cOps;
      std::list<enum BaseType> btls;

      for (std::list<AssociationElement*>::iterator i = ops.begin(); 
            i != ops.end(); i++) {

            GenCode lgc = GenCode(gc.container);
            assert((*i)->formal == NULL); // FIXME
            assert((*i)->actual != NULL);

            (*i)->actual->accept(lgc);
            cOps.push_back(lgc.sourceRegs);
            btls.push_back((*i)->actual->baseType);
      }

      return this->calculate(*gc.container, cOps, btls);
}

RegisterSet
00052 GCBuiltinsShortCircuit::emitCode(
      GenCode &gc,
      std::list<AssociationElement*> ops
) const
{
      // FIXME this doesn't work for composite types, e.g. bit-vectors.
      assert(ops.size() == 2);

      std::list<AssociationElement*>::iterator i = ops.begin();
      Label *out = LabelFactory::getLabel("builtin_shortcut_result");

      // result = <default>
      Register *result = 
            RegisterFactory::getRegister(OP_TYPE_INTEGER);
      Mov *def = new Mov(new ImmediateOperand(this->getDefault()), result);
      gc.container->addCode(def);

      // leftop = (..)
      Operand *leftOp = this->evaluate(gc.container, **i);
      i++;
      
      // if leftop == <shortCut> goto out
      Je *shortCut = 
            new Je(leftOp, 
                  new ImmediateOperand(this->getShortCut()), 
                  out);
      gc.container->addCode(shortCut);

      // rightop = (..)
      Operand *rightOp = this->evaluate(gc.container, **i);

      // if rightop == <shortCut> goto out
      Je *shortCut2 = 
            new Je(rightOp, 
                  new ImmediateOperand(this->getShortCut()),
                  out);
      gc.container->addCode(shortCut2);
      
      // result = 1 - <default>
      Mov *altRes = 
            new Mov(new ImmediateOperand(1 - this->getDefault()), result);
      gc.container->addCode(altRes);
      
      // out:
      gc.container->addCode(out);

      RegisterSet ret = RegisterSet(*gc.container);
      ret.setValue(result);

      return ret;
}

Operand *
00105 GCBuiltinsShortCircuit::evaluate(
      CodeContainer *cc,
      AssociationElement &assoc
)
{
      GenCode gc = GenCode(cc);
      // FIXME composites
      assert(assoc.formal == NULL);
      assert(assoc.actual != NULL);
      assoc.actual->accept(gc);

      Operand *ret = 
            gc.sourceRegs.getValue(assoc.actual->baseType);
      assert(ret != NULL);
      return ret;
}

RegisterSet
00123 GCBuiltinsUnop::calculate(
      CodeContainer &cc,
      std::list<RegisterSet> ops,
      std::list<enum BaseType> btl
) const
{
      assert(ops.size() == 1);
      RegisterSet r = *ops.begin();

      Operand *value = r.getValue(btl.front());

      Register *result = this->calcUnOp(cc, value);
      RegisterSet rset = RegisterSet(cc);
      rset.setValue(result);
      return rset;
}

RegisterSet
00141 GCBuiltinsBinOp::calculate(
      CodeContainer &cc,
      std::list<RegisterSet> ops,
      std::list<enum BaseType> btl
) const
{
      assert(ops.size() == 2);
      std::list<RegisterSet>::const_iterator i = ops.begin();
      std::list<enum BaseType>::const_iterator j = btl.begin();

      RegisterSet left = *i;
      enum BaseType leftBT = *j;

      i++; j++;
      RegisterSet right = *i;
      enum BaseType rightBT = *j;

      Operand *leftOp = left.getValue(leftBT);
      Operand *rightOp = right.getValue(rightBT);

      assert(leftOp != NULL);
      assert(rightOp != NULL);

      Register *result = this->calcBinOp(cc, leftOp, rightOp);
      RegisterSet rset = RegisterSet(cc);
      rset.setValue(result);

      return rset;
}


/* ********************** implementation of builtins ******************* */

Register *
00175 GCBuiltinsNot::calcUnOp(CodeContainer &cc, Operand *op) const
{
      // not for bit, boolean: 1 - op
      // (which is only valid if '1'/true == 1 and '0'/false == 0)
      assert(VHDL_TRUE == 1);
      assert(VHDL_FALSE == 0);

      Register *result = RegisterFactory::getRegister(OP_TYPE_INTEGER);
      Sub *sub = new Sub(ImmediateOperand::getOne(), op, result);
      cc.addCode(sub);

      return result;
}

Register *
00190 GCBuiltinsXor::calcBinOp(
      CodeContainer &cc, 
      Operand *left, 
      Operand *right
) const
{
      //t = left + right.
      //Xor = t == 2 ? 0 : t;
      Register *lsumr = RegisterFactory::getRegister(OP_TYPE_INTEGER);
      Add *add = new Add(left, right, lsumr);
      cc.addCode(add);

      ImmediateOperand *two = 
            new ImmediateOperand(static_cast<universal_integer>(2));

      Label *out = LabelFactory::getLabel("xor_out");

      Jb *jb = new Jb(lsumr, two, out);
      cc.addCode(jb);

      Mov *mov = new Mov(ImmediateOperand::getZero(), lsumr);
      cc.addCode(mov);

      cc.addCode(out);

      return lsumr;
}

Register *
00219 GCBuiltinsXnor::calcBinOp(
      CodeContainer &cc, 
      Operand *left, 
      Operand *right
) const
{
      //xnor : not xor -> 1 - xor(left, right)
      Register *ret = GCBuiltinsXor::calcBinOp(cc, left, right);
      Register *res = RegisterFactory::getRegister(OP_TYPE_INTEGER);

      Sub *sub = new Sub(ImmediateOperand::getOne(), ret, res);
      cc.addCode(sub);

      return res;
}

Register *
00236 GCBuiltinsCompare::calcBinOp(
      CodeContainer &cc,
      Operand *left,
      Operand *right
) const
{
      Register *result = RegisterFactory::getRegister(OP_TYPE_INTEGER);
      ImmediateOperand *default_op = 
            new ImmediateOperand(this->getDefaultValue());

      Mov *mov = new Mov(default_op, result);
      cc.addCode(mov);

      Label *out = LabelFactory::getLabel("compare_out");
      OpCode *branch = this->emitBranch(left, right, out);
      cc.addCode(branch);

      ImmediateOperand *non_default_op = 
            new ImmediateOperand(1 - this->getDefaultValue());
      Mov *mov2 = new Mov(non_default_op, result);
      cc.addCode(mov2);

      cc.addCode(out);

      return result;
}

OpCode *
00264 GCBuiltinsEqual::emitBranch(Operand *left, Operand *right, Label *out) const
{
      return new Je(left, right, out);
}

OpCode *
00270 GCBuiltinsInEqual::emitBranch(Operand *left, Operand *right, Label *out) const
{
      return new Jne(left, right, out);
}

OpCode *
00276 GCBuiltinsLess::emitBranch(Operand *left, Operand *right, Label *out) const
{
      return new Jb(left, right, out);
}

OpCode *
00282 GCBuiltinsLessEqual::emitBranch(
      Operand *left, 
      Operand *right, 
      Label *out
) const
{
      return new Jbe(left, right, out);
}

OpCode *
00292 GCBuiltinsGreater::emitBranch(
      Operand *left, 
      Operand *right, 
      Label *out
) const
{
      return new Jbe(left, right, out);
}

OpCode *
00302 GCBuiltinsGreaterEqual::emitBranch(
      Operand *left, 
      Operand *right, 
      Label *out
) const
{
      return new Jb(left, right, out);
}

Register *
00312 GCBuiltinsUnaryMinus::calcUnOp(CodeContainer &cc, Operand *op) const
{
      // unary minus: 0 - <value>
      Register *result = RegisterFactory::getRegister(op->type);
      Sub *sub = new Sub(ImmediateOperand::getZero(), op, result);
      cc.addCode(sub);

      return result;
}

RegisterSet
00323 GCBuiltinsIdentity::emitCode(
      GenCode &gc, 
      std::list<AssociationElement*> ops
) const
{
      assert(ops.size() == 1);
      AssociationElement *elem = ops.front();

      assert(elem->formal == NULL);
      assert(elem->actual != NULL);

      GenCode lgc = GenCode(gc.container);
      elem->actual->accept(lgc);

      // just pass on the RegisterSet of the argument.
      return lgc.sourceRegs;
}

Register *
00342 GCBuiltinsAbs::calcUnOp(CodeContainer &cc, Operand *op) const
{

      //    res = op
      //    if 0 < res goto out
      //    res = 1 - res
      // out:
      //
      Register *result = RegisterFactory::getRegister(op->type);
      Mov *ir = new Mov(op, result);
      cc.addCode(ir);

      Label *absOut = LabelFactory::getLabel("abs_out");
      Jb *goOut = new Jb(ImmediateOperand::getZero(), op, absOut);
      cc.addCode(goOut);

      Sub *invert = new Sub(ImmediateOperand::getZero(), op, result);
      cc.addCode(invert);

      cc.addCode(absOut);

      return result;
}

}; /* namespace ast */

Generated by  Doxygen 1.6.0   Back to index