Logo Search packages:      
Sourcecode: fauhdlc version File versions

GCTypes.cpp

/* $Id: GCTypes.cpp 4323 2009-01-27 13:48:12Z potyra $ 
 *
 * Generate intermediate code, related to type handling.
 *
 * 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/GCTypes.hpp"

#include <cassert>
#include "frontend/ast/RecordType.hpp"
#include "frontend/ast/RangeConstraintType.hpp"
#include "frontend/ast/UnconstrainedArrayType.hpp"
#include "frontend/ast/PhysicalType.hpp"
#include "frontend/ast/EnumerationType.hpp"
#include "frontend/ast/ConstInteger.hpp"
#include "frontend/ast/ConstReal.hpp"
#include "frontend/ast/ConstArray.hpp"
#include "frontend/reporting/ErrorRegistry.hpp"
#include "frontend/reporting/CompileError.hpp"
#include "util/MiscUtil.hpp"
#include "intermediate/operands/ImmediateOperand.hpp"
#include "intermediate/operands/IndirectOperand.hpp"
#include "intermediate/operands/RegisterFactory.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"
#include "intermediate/opcodes/Jmp.hpp"
#include "intermediate/opcodes/IMul.hpp"
#include "intermediate/opcodes/Add.hpp"
#include "intermediate/opcodes/Sub.hpp"
#include "intermediate/opcodes/Call.hpp"
#include "intermediate/container/Label.hpp"
#include "intermediate/container/LabelFactory.hpp"
#include "intermediate/container/Data.hpp"
#include "intermediate/container/TypeFactory.hpp"
#include "intermediate/container/Type.hpp"
#include "intermediate/container/TypeElement.hpp"
#include "intermediate/container/TypeFactory.hpp"


namespace ast {

/* import some names into current namespace, just to avoid lengthy types */
using namespace intermediate;

universal_integer
00054 GCTypes::calcArrayBound(
      const std::list<DiscreteRange*> &indices
)
{
      universal_integer card = 1;

      for (std::list<DiscreteRange*>::const_iterator i = indices.begin(); 
            i != indices.end(); i++) {
      
            card *= (*i)->getArraySize();
      }

      if (card < 0) {
            // null array
            return 0;
      }

      return card;
}



/*
 * ================== GENTYPEELEMENTS ===============
 */

00080 GCTypes::GenTypeElements::GenTypeElements(
      bool addInitializer,
      const char *uErrMsg,
      const AstNode &errNode,
      const AstNode *constInitExp
) :         composite(std::list<TypeElement*>()),
            constraint(NULL),
            addInit(addInitializer),
            mungeIndices(false),
            uAErrMsg(uErrMsg),
            errorNode(errNode),
            isForeign(false),
            constInit(constInitExp)
{
}

void
00097 GCTypes::GenTypeElements::visit(RangeConstraintType &node)
{
      switch(node.baseType) {
      case BASE_TYPE_INTEGER:
            this->processDR<ConstInteger>(*node.constraint, 
                                    &node);
            break;

      case BASE_TYPE_REAL:
            this->processDR<ConstReal>(*node.constraint, &node);
            break;

      default:
            assert(false);
      }
}

template <typename T>
void
00116 GCTypes::GenTypeElements::processDR(
      DiscreteRange &node, 
      TypeDeclaration *actualType
)
{
      ImmediateOperand *init = NULL;
      if (this->addInit) {
            const T *iv;
            if (this->constInit != NULL) {
                  iv = dynamic_cast<const T*>(this->constInit);
            } else {
                  assert(node.from != NULL);
                  assert(node.to != NULL);
                  iv = dynamic_cast<const T*>(node.from);
            }

            // FIXME can fail, if not const initializer from if-path
            assert(iv != NULL);

            init = new ImmediateOperand(iv->value);
      }
      
      TypeElement *te = 
            new TypeElement(TypeFactory::getTypeName(
                                    actualType->baseType),
                        init,
                        this->calcArrayBound());
      
      this->composite.push_back(te);
      this->referredTypes.push_back(actualType);
}

void
00149 GCTypes::GenTypeElements::visit(EnumerationType &node)
{
      ImmediateOperand *init = NULL;
      if (this->addInit) {
            universal_integer iv = 0;
            if (this->constInit != NULL) {
                  const ConstInteger *ci = 
                        dynamic_cast<const ConstInteger*>(
                              this->constInit);

                  // FIXME can fail if not const
                  assert(ci != NULL);
                  iv = ci->value;
            }
            init = new ImmediateOperand(iv);
      }

      TypeElement *te = 
            new TypeElement(TypeFactory::getTypeName(BASE_TYPE_INTEGER),
                        init, this->calcArrayBound());

      this->composite.push_back(te);
      this->referredTypes.push_back(&node);
}

void
00175 GCTypes::GenTypeElements::visit(SubtypeIndication &node)
{
      switch (node.baseType) {
      case BASE_TYPE_INTEGER:
      case BASE_TYPE_ENUM:
            this->processSI<ConstInteger>(node);
            // return early.
            return;

      case BASE_TYPE_REAL:
            this->processSI<ConstReal>(node);
            // return early.
            return;

      case BASE_TYPE_ARRAY:
            this->processSIArray(node);
            break;

      case BASE_TYPE_RECORD:
            // doesn't really make sense imho... but let's traverse to the
            // base type. (but it is allowed by lrm)
            break;

      default:
            // must not happen
            assert(false);
      }

      TypeDeclaration *t = const_cast<TypeDeclaration*>(node.declaration);
      t->accept(*this);
}

template <typename T>
void
GCTypes::GenTypeElements::processSI(SubtypeIndication &node)
{
      if (node.constraint != NULL) {
            this->processDR<T>(*node.constraint, &node);
            return;
      }

      // no constraint set, traverse to parent
      TypeDeclaration *fixme = 
            const_cast<TypeDeclaration*>(node.declaration);
      fixme->accept(*this);
}

void
00223 GCTypes::GenTypeElements::visit(RecordType &node)
{
      assert(this->indexConstraint.empty() || this->mungeIndices);
      TypeElement *te = new TypeElement(node.getICName(), 
                              NULL, 
                              this->calcArrayBound());
      this->composite.push_back(te);
      this->referredTypes.push_back(&node);
}

void
00234 GCTypes::GenTypeElements::visit(UnconstrainedArrayType &node)
{
      if (this->indexConstraint.empty() && (this->uAErrMsg != NULL)) {
            CompileError *ce = 
                  new CompileError(this->errorNode, this->uAErrMsg);
            ErrorRegistry::addError(ce);
            return;
      }

      std::string name = "";
      assert(node.containerType != NULL);

      switch (node.containerType->baseType) {
      case BASE_TYPE_INTEGER:
      case BASE_TYPE_REAL:
      case BASE_TYPE_ENUM:
            node.containerType->accept(*this);
            return;

      case BASE_TYPE_RECORD: {
            name = this->findName(*node.containerType);
            TypeElement *te = new TypeElement(name, NULL, 
                                    this->calcArrayBound());
            this->composite.push_back(te);
            this->referredTypes.push_back(node.containerType);
            return;
          }
      case BASE_TYPE_ARRAY: {
            bool mibackup = this->mungeIndices;

            this->mungeIndices = true;
            node.containerType->accept(*this);
            this->mungeIndices = mibackup;

            return;
          }
      default:
            break;
      }

      /* not reached */
      assert(false);
}

void
00279 GCTypes::GenTypeElements::visit(PhysicalType &node)
{
      assert(node.constraint != NULL);
      assert(node.baseType == BASE_TYPE_INTEGER);
      this->processDR<ConstInteger>(*node.constraint, &node);
}

void
GCTypes::GenTypeElements::processSIArray(SubtypeIndication &node)
{
      if (node.indexConstraint != NULL) {
            if ((! (this->indexConstraint.empty())) 
             && (! this->mungeIndices)) {
                  // only one index constraint allowed, 
                  // lrm 3.2.1.1
                  std::string msg = std::string("Index "
                        "constraint already defined at ");
                  DiscreteRange *f = 
                        this->indexConstraint.front();
                  msg += util::MiscUtil::toString(f->location);
                  CompileError *ce = 
                        new CompileError(node, msg);
                  ErrorRegistry::addError(ce);
                  return;
            }

            // munge indices together
            this->indexConstraint.insert(this->indexConstraint.end(),
                        node.indexConstraint->begin(), 
                        node.indexConstraint->end());
            this->mungeIndices = false;
      }
}


void
GCTypes::GenTypeElements::reset(void)
{
      // FIXME what about other member? (e.g. mungeIndices)
      this->indexConstraint.clear();
      this->constraint = NULL;
}

std::list<DiscreteRange*>
00323 GCTypes::GenTypeElements::getIndices(void) const
{
      return this->indexConstraint;
}

std::string
00329 GCTypes::GenTypeElements::findName(const TypeDeclaration &node)
{
      // make sure it's an array or record
      switch (node.baseType) {
      case BASE_TYPE_ARRAY:
      case BASE_TYPE_RECORD:
            break;
      default:
            assert(false);
      }

      if (node.name != NULL) {
            assert(! node.pathName.empty());
            return node.getICName();
      }

      // unnamed, so assume that it is a SubtypeIndication
      const SubtypeIndication *si = 
            dynamic_cast<const SubtypeIndication*>(&node);

      if (si == NULL) {
            // FIXME possible that it is an anonymous type?
            assert(false);
      }

      return GCTypes::GenTypeElements::findName(*(si->declaration));
}

universal_integer
00358 GCTypes::GenTypeElements::calcArrayBound(void) const
{
      return GCTypes::calcArrayBound(this->indexConstraint);
}

/*
 * =====================  GENTYPES  =================
 */
void
GCTypes::GenTypes::visit(EnumerationType &node)
{
      // not a composite, don't create type for this one.
}

void
GCTypes::GenTypes::visit(RangeConstraintType &node)
{
      // not a composite, don't create type for this one.
}

void
GCTypes::GenTypes::visit(PhysicalType &node)
{
      // not a composite, don't create type for this one.
}

void
GCTypes::GenTypes::visit(RecordType &node)
{
      assert(node.elements != NULL);
      assert(node.name != NULL);

      GenTypeElements gte = 
            GenTypeElements(false, 
                        "Unconstraint array not allowed in a "
                        "record type",
                        node,
                        NULL);

      for (std::list<RecordTypeElement*>::iterator i = 
            node.elements->begin(); i != node.elements->end(); i++) {

            assert((*i)->subtype != NULL);
            (*i)->subtype->accept(gte);
            gte.reset();
      }

      this->type = TypeFactory::getType(node.getICName(), gte.composite);
}

void
GCTypes::GenTypes::visit(UnconstrainedArrayType &node)
{
      // do nothing for unconstraint arrays, as these can never
      // result in a intermediate code type.
}

void
GCTypes::GenTypes::visit(SubtypeIndication &node)
{
      if (node.name == NULL) {
            // must not be an anonymous type!
            assert(false);
            return;
      }

      switch (node.baseType) {
      case BASE_TYPE_RECORD:
            // FIXME this is allowed by LRM!
            assert(false);
            return;

      case BASE_TYPE_ARRAY:
            break;
      default:
            // not composite -> do nothing.
            // (non-composite types don't need to be reflected
            // in the intermediate code, as these will always 
            // be represented with universal_integer/universal_real)
            return;
      }

      // composite type
      GenTypeElements gte = 
            GenTypeElements(false, 
                        "Unconstraint array not allowed in a "
                        "composite type",
                        node,
                        NULL);
      node.accept(gte);
      this->type = TypeFactory::getType(node.getICName(), gte.composite);
}

}; /* namespace ast */

Generated by  Doxygen 1.6.0   Back to index