Logo Search packages:      
Sourcecode: fauhdlc version File versions

GCBuiltins.hpp

/* $Id: GCBuiltins.hpp 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.
 */

#ifndef __GC_BUILTINS_HPP_INCLUDED
#define __GC_BUILTINS_HPP_INCLUDED

#include "frontend/visitor/GenCode.hpp"
#include "frontend/misc/BuiltinSymbolTable.hpp"
#include <list>
#include "intermediate/opcodes/OpCode.hpp"
#include "intermediate/operands/RegisterFactory.hpp"
#include "intermediate/opcodes/Sub.hpp"
#include "intermediate/opcodes/Add.hpp"
#include "intermediate/opcodes/IMul.hpp"
#include "intermediate/opcodes/Div.hpp"

namespace ast {

//! abstract base class for an arbitrary builtin operator.
/** GCBuiltins is the abstract base class for all builtin operators.
 *  To generate code, the following functions must always get called:
 *
 *    reset();
 *     generate code to evaluate first operand here ...
 *    shortCutfirstOp(cc, firstOp);
 *     generate code to evaluate the remaining operands here ...
 *    emitCode(cc, operands);
 *
 *  The operands parameter of emitCode must contain *all* operands.
 */
00038 class GCBuiltins {
public:
      //! virtual dummy d'tor.
00041       virtual ~GCBuiltins() {}

      //! generic abstract interface to emit code for a builtin function
      /** @param gc Code generator instance.
       *  @param ops list of operands.
       *  @return RegisterSet containing the result of the operands.
       */
      virtual RegisterSet
      emitCode(GenCode &gc, std::list<AssociationElement*> ops) const = 0;
};

//! abstract base class for non-short-circuit operators
00053 class GCBuiltinsNoShortCircuit : public GCBuiltins {
private:
      //! generic abstract interface to emit code for a builtin function
      /** @param gc Code generator instance.
       *  @param ops list of operands.
       *  @return RegisterSet containing the result of the operands.
       */
      virtual RegisterSet
      emitCode(GenCode &gc, std::list<AssociationElement*> ops) const;

protected:
      //! emit code to calculate the result
      /** @param cc container to add generated code to.
       *  @param ops RegisterSets containing the operands.
       *  @return RegisterSet containing the result.
       */
      virtual RegisterSet 
      calculate(
            intermediate::CodeContainer &cc, 
            std::list<RegisterSet> ops,
            std::list<enum BaseType> btl) const = 0;
};

//! abstract base class for all binary short-circuit operators.
00077 class GCBuiltinsShortCircuit : public GCBuiltins {
private:
      //! generic abstract interface to emit code for a builtin function
      /** 
       * res = <default>
       * if (left == <shortCut>) {
         *  goto out
       * }
       * if (right == <shortCut>) {
       *    goto out
       *    res = < 1 - default >
       * }
       *
       *  @param gc Code generator instance.
       *  @param ops list of operands.
       *  @return RegisterSet containing the result of the operands.
       */
      virtual RegisterSet
      emitCode(GenCode &gc, std::list<AssociationElement*> ops) const;

protected:
      /** determine the default value, which gets used if the comparison
       *  against getShortCut is equal.
       *  @return the default value of the short circuit operator in the
       *          range between 0 and 1.
       */
      virtual universal_integer getDefault(void) const = 0;

      /** determine the value to check against, if the shortcut condition
       *  matches.
       *  @return if the operand is equal to the return value, the default
       *          value will be used as result.
       */
      virtual universal_integer getShortCut(void) const = 0;
private:
      //! evaluate the result of one assocation and return it in an operand
      /** @param cc CodeContainer to add code to.
       *  @param assoc association to evaluate. (FIXME interface ?)
       *  @return operand containing the result */
      static intermediate::Operand *
      evaluate(intermediate::CodeContainer *cc, AssociationElement &assoc);
};

//! implementation of the "AND" short-circuit operator.
00121 class GCBuiltinsAnd : public GCBuiltinsShortCircuit {
private:
00123       virtual universal_integer getDefault(void) const {
            return 0;
      }

00127       virtual universal_integer getShortCut(void) const {
            return 0;
      }
};

//! implementation of the "OR" short-circuit operator.
00133 class GCBuiltinsOr : public GCBuiltinsShortCircuit {
private:
00135       virtual universal_integer getDefault(void) const {
            return 1;
      }

00139       virtual universal_integer getShortCut(void) const {
            return 1;
      }
};

//! implementation of the "NAND" short-circuit operator.
00145 class GCBuiltinsNand : public GCBuiltinsShortCircuit {
private:
00147       virtual universal_integer getDefault(void) const {
            return 1;
      }

00151       virtual universal_integer getShortCut(void) const {
            return 0;
      }
};

//! implementation of the "NOR" short-circuit operator.
00157 class GCBuiltinsNor : public GCBuiltinsShortCircuit {
private:
00159       virtual universal_integer getDefault(void) const {
            return 0;
      }

00163       virtual universal_integer getShortCut(void) const {
            return 1;
      }
};

//! no-short circuit unary operators for non-composite types.
00169 class GCBuiltinsUnop : public GCBuiltinsNoShortCircuit {
private:
      //! emit code to calculate the result
      /** @param ops list of operands
       *  @return RegisterSet containing the result.
       */
      virtual RegisterSet 
      calculate(
            intermediate::CodeContainer &cc, 
            std::list<RegisterSet> ops,
            std::list<enum BaseType> btl) const;

protected:
      //! calculate the result of the unary operator
      /** @param cc container to add generated code to.
       *  @param op operand
       *  @return Register containing the result.
       */
      virtual intermediate::Register *
      calcUnOp(
            intermediate::CodeContainer &cc,
            intermediate::Operand *op) const = 0;
};

//! no-short circuit binary opartors for non-composite types.
00194 class GCBuiltinsBinOp : public GCBuiltinsNoShortCircuit {
private:
      //! emit code to calculate the result
      /** @param ops list of operands
       *  @return RegisterSet containing the result.
       */
      virtual RegisterSet 
      calculate(
            intermediate::CodeContainer &cc, 
            std::list<RegisterSet> ops,
            std::list<enum BaseType> btl) const;

protected:
      //! calculate the result of the binary operator
      /** @param cc container to add generated code to.
       *  @param left left operand
       *  @param right right operand.
       *  @return Register containing the result.
       */
      virtual intermediate::Register *
      calcBinOp(
            intermediate::CodeContainer &cc,
            intermediate::Operand *left,
            intermediate::Operand *right) const = 0;
};


//! unary not for boolean and bit.
00222 class GCBuiltinsNot : public GCBuiltinsUnop {
private:
      //! emit code for an unary not (bit, boolean)
      virtual intermediate::Register *
      calcUnOp(
            intermediate::CodeContainer &cc, 
            intermediate::Operand *op) const;
};

//! xor for boolean and bit.
00232 class GCBuiltinsXor : public GCBuiltinsBinOp {
protected:
      //! calculate the result of XOR
      /** @param cc container to add generated code to.
       *  @param left left operand
       *  @param right right operand.
       *  @return Register containing the result.
       */
      virtual intermediate::Register *
      calcBinOp(
            intermediate::CodeContainer &cc,
            intermediate::Operand *left,
            intermediate::Operand *right) const;

};

//! xnor for boolean and bit.
00249 class GCBuiltinsXnor : public GCBuiltinsXor {
private:
      //! calculate the result of XOR
      /** @param cc container to add generated code to.
       *  @param left left operand
       *  @param right right operand.
       *  @return Register containing the result.
       */
      virtual intermediate::Register *
      calcBinOp(
            intermediate::CodeContainer &cc,
            intermediate::Operand *left,
            intermediate::Operand *right) const;

};

//! base class for comparison operators for non-composite types.
00266 class GCBuiltinsCompare : public GCBuiltinsBinOp {
private:
      //! calculate the result of XOR
      /** @param cc container to add generated code to.
       *  @param left left operand
       *  @param right right operand.
       *  @return Register containing the result.
       */
      virtual intermediate::Register *
      calcBinOp(
            intermediate::CodeContainer &cc,
            intermediate::Operand *left,
            intermediate::Operand *right) const;

protected:
      //! emit the comparison operation branch opcode.
      /** If the branch is not taken, 1-default value will be the result.
       *  If the branch is taken, default value will be the result.
       *  @param left left operand to compare
       *  @param right right operand to compare
       *  @param out branch target that uses the default value.
       *  @return generated branch opcode.
       */
      virtual intermediate::OpCode *
      emitBranch(
            intermediate::Operand *left, 
            intermediate::Operand *right, 
            intermediate::Label *out) const = 0;
      
      //! get the default value of the comparison operator.
      /** @return default value of the comparison operator.
       */
      virtual universal_integer getDefaultValue(void) const = 0;
};

//! equality for non-composite types.
00302 class GCBuiltinsEqual : public GCBuiltinsCompare {
private:
      //! emit a je.
      virtual intermediate::OpCode *
      emitBranch(
            intermediate::Operand *left, 
            intermediate::Operand *right, 
            intermediate::Label *out) const;

00311       virtual universal_integer getDefaultValue(void) const {
            return VHDL_TRUE;
      }
};

//! inequality for non-composite types.
00317 class GCBuiltinsInEqual : public GCBuiltinsCompare {
private:
      //! emit a jne
      virtual intermediate::OpCode *
      emitBranch(
            intermediate::Operand *left, 
            intermediate::Operand *right, 
            intermediate::Label *out) const;

00326       virtual universal_integer getDefaultValue(void) const {
            return VHDL_TRUE;
      }
};

//! less than for non-composite types.
00332 class GCBuiltinsLess : public GCBuiltinsCompare {
private:
      //! emit a jb
      virtual intermediate::OpCode *
      emitBranch(
            intermediate::Operand *left, 
            intermediate::Operand *right, 
            intermediate::Label *out) const;

00341       virtual universal_integer getDefaultValue(void) const {
            return VHDL_TRUE;
      }
};

//! less or equal for non-composite types.
00347 class GCBuiltinsLessEqual : public GCBuiltinsCompare {
private:
      //! emit a jbe
      virtual intermediate::OpCode *
      emitBranch(
            intermediate::Operand *left, 
            intermediate::Operand *right, 
            intermediate::Label *out) const;

00356       virtual universal_integer getDefaultValue(void) const {
            return VHDL_TRUE;
      }
};

//! greater than for non-composite types.
00362 class GCBuiltinsGreater : public GCBuiltinsCompare {
private:
      //! emit a jbe
      virtual intermediate::OpCode *
      emitBranch(
            intermediate::Operand *left, 
            intermediate::Operand *right, 
            intermediate::Label *out) const;

00371       virtual universal_integer getDefaultValue(void) const {
            return VHDL_FALSE;
      }
};

//! greater or equal for non-composite types.
00377 class GCBuiltinsGreaterEqual : public GCBuiltinsCompare {
private:
      //! emit a jb
      virtual intermediate::OpCode *
      emitBranch(
            intermediate::Operand *left, 
            intermediate::Operand *right, 
            intermediate::Label *out) const;

00386       virtual universal_integer getDefaultValue(void) const {
            return VHDL_FALSE;
      }
};

//! unary - (negation) for range constraint/physical types.
00392 class GCBuiltinsUnaryMinus : public GCBuiltinsUnop {
private:
      //! calculate the result of the unary -.
      /** @param cc container to add generated code to.
       *  @param op operand
       *  @return Register containing the result.
       */
      virtual intermediate::Register *
      calcUnOp(
            intermediate::CodeContainer &cc,
            intermediate::Operand *op) const;
};

//! identity (unary plus)
00406 class GCBuiltinsIdentity : public GCBuiltins {
private:
      virtual RegisterSet
      emitCode(GenCode &gc, std::list<AssociationElement*> ops) const;
};

//! unary abs for range constraint/physical types.
00413 class GCBuiltinsAbs : public GCBuiltinsUnop {
private:
      //! calculate absolute value.
      virtual intermediate::Register *
      calcUnOp(
            intermediate::CodeContainer &cc,
            intermediate::Operand *op) const;
};

//! template class for binary mathematical builtins
/** template class for binary mathematical builtins that can use 
 *  a direct intermediate opcode for evaluation.
 */
template <typename T>
00427 class GCBuiltinsBinaryMath : public GCBuiltinsBinOp {
private:
      //calculate left + right
      virtual intermediate::Register *
00431       calcBinOp(
            intermediate::CodeContainer &cc,
            intermediate::Operand *left,
            intermediate::Operand *right) const {
            
            assert(left->type == right->type);
            intermediate::Register *result = 
                  intermediate::RegisterFactory::getRegister(
                                                left->type);

            T *operation = new T(left, right, result);
            cc.addCode(operation);

            return result;
      };
};

//! binary plus.
00449 class GCBuiltinsPlus : public GCBuiltinsBinaryMath<intermediate::Add> {
};

//! binary minus.
00453 class GCBuiltinsMinus : public GCBuiltinsBinaryMath<intermediate::Sub> {
};

//! binary multiplication.
00457 class GCBuiltinsMult : public GCBuiltinsBinaryMath<intermediate::IMul> {
};

//! binary division.
00461 class GCBuiltinsDiv : public GCBuiltinsBinaryMath<intermediate::Div> {
};




}; /* namespace ast */

#endif /* __GC_BUILTINS_HPP_INCLUDED */

Generated by  Doxygen 1.6.0   Back to index