Logo Search packages:      
Sourcecode: fauhdlc version File versions

FAUhdlc.cpp

/* $Id: FAUhdlc.cpp 4323 2009-01-27 13:48:12Z potyra $ 
 *
 * FAUhdlc: main class to setup and execute compilation.
 *
 * Copyright (C) 2007-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 <cstring>
#include <fstream>
#include <iostream>
#include <cassert>
extern "C" {
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#include <getopt.h>
#undef _GNU_SOURCE
#else /* _GNU_SOURCE not externally defined */
#include <getopt.h>
#endif /* _GNU_SOURCE externally defined */
};
#include "compiler/FAUhdlc.hpp"
#include "frontend/reporting/ErrorRegistry.hpp"
#include "frontend/newparser/ParserDriver.hpp"
#include "util/MiscUtil.hpp"
#include "util/GarbageCollect.hpp"
#include "frontend/visitor/DotVisitor.hpp"
#include "frontend/misc/BuiltinSymbolTable.hpp"
#include "frontend/visitor/ResolveTypes.hpp"
#include "frontend/visitor/SetPathName.hpp"
#include "frontend/visitor/GatherImplicits.hpp"
#include "frontend/visitor/GenCode.hpp"
#include "frontend/visitor/ConstantPropagation.hpp"
#include "frontend/visitor/CheckLoops.hpp"
#include "frontend/visitor/CheckAccessMode.hpp"
#include "frontend/visitor/NormalizeAssocLists.hpp"
#include "frontend/visitor/WaitConditions.hpp"
#include "frontend/visitor/WarnUnused.hpp"
#include "intermediate/visitor/PrintCode.hpp"

namespace compiler {

00045 FAUhdlc::FAUhdlc() : topNode(NULL), 
                  parseOnly(false), 
                  dotParse(false), 
                  resultCode(FAUHDLC_EXIT_SUCCESS),
                  dotParseFile(NULL),
                  outputFile(NULL),
                  symbolTable(NULL),
                  iTopNode(NULL),
                  dotConst(false),
                  dotConstFile(NULL),
                  freeStanding(false)
{
}

00059 FAUhdlc::~FAUhdlc() 
{
      // cleanup memory (only useful for leak checking)
      for (std::list<struct FAUhdlc::LibFile*>::iterator i =
            this->sourceFiles.begin(); i != this->sourceFiles.end(); 
            i++) {

            delete (*i)->filename;
            delete *i;
      }
      util::MiscUtil::terminate(this->topNode);
      if (this->symbolTable) {
            delete this->symbolTable;
      }
      util::MiscUtil::terminate(this->iTopNode);
}

void
00077 FAUhdlc::parseCmdLine(int argc, char** argv) 
{
      const char *currentLib = "work";
      bool success = true;
      bool again = true;
      int c;
      struct option l_opts[] = {
            /* name, has_arg, *flag, val */
            {"parse-only", 0, NULL, 'p'},
            {"dot-parse", 1, NULL, 'd'},
            {"dot-const", 1, NULL, 'c'},
            {"lib", 1, NULL, 'l'},
            {"output", 1, NULL, 'o'},
            {"help", 0, NULL, 'h'},
            {"freestanding", 0, NULL, 'f'},
            {0, 0, 0, 0}
      };



      while (again) {
            c = getopt_long(argc, argv, "-pd:c:l:o:hW:", l_opts, NULL);

            switch (c) {
            case -1: /* no more options */
                  again = false;
                  break;

            case 1: /* "non"-option, name of compile file */ {
                  struct FAUhdlc::LibFile *f = new struct FAUhdlc::LibFile();
                  f->filename = new std::string(optarg);
                  f->library = currentLib;

                  this->sourceFiles.push_back(f);
                  break;
                }
            case 'p': /* parse-only */
                  this->parseOnly = true;
                  break;

            case 'd': /* dot-parse=<filename> */
                  this->dotParse = true;
                  this->dotParseFile = optarg;
                  break;

            case 'c': /* dot-const=<filename> */
                  this->dotConst = true;
                  this->dotConstFile = optarg;
                  break;

            case 'l': /* lib=<libname> */
                  currentLib = optarg;
                  break;

            case 'o': /* output=<filename> */
                  this->outputFile = optarg;
                  break;

            case 'h': /* help */
                  success = false;
                  break;

            case 'W': /* warning options */
                  if (strcmp("error", optarg) == 0) {
                        ast::ErrorRegistry::setWerror(true);
                  } else {
                        success = false;
                  }
                  break;

            case 'f': /* freestanding */
                  this->freeStanding = true;
                  break;

            };
      }

      /** at least one file? */
      if (this->sourceFiles.size() == 0) {
            success = false;
      }

      if (! success) {
            this->resultCode = FAUHDLC_EXIT_COMMAND_ARGS;
            this->usage(std::cerr);
      }
}

int 
00166 FAUhdlc::run(void)
{
      if (this->resultCode != FAUHDLC_EXIT_SUCCESS) {
            return this->resultCode;
      }

      this->doParse();

      if (   (this->resultCode != FAUHDLC_EXIT_SUCCESS) 
            || (this->topNode == NULL)
          || ast::ErrorRegistry::hasErrors()) {

            this->putCompileMessages();
            return this->resultCode;
      }

      if (this->parseOnly) {
            return this->resultCode;
      }

      try {
            this->doSemanticAnalysis();
      } catch (std::runtime_error f) {
            this->resultCode = FAUHDLC_EXIT_EXCEPTION;
            std::cerr << f.what() << std::endl;
      } catch (...) {
            this->resultCode = FAUHDLC_EXIT_EXCEPTION;
            std::cerr << "unknown exception occured." << std::endl;
      }

      this->putCompileMessages();

      if (this->resultCode != FAUHDLC_EXIT_SUCCESS) {
            return this->resultCode;
      }

      try {
            this->doIntermediateTransform();
      } catch (std::runtime_error f) {
            this->resultCode = FAUHDLC_EXIT_EXCEPTION;
            std::cerr << f.what() << std::endl;
      } catch (...) {
            this->resultCode = FAUHDLC_EXIT_EXCEPTION;
            std::cerr << "unknown exception occured." << std::endl;
      }

      return this->resultCode;
}

void
00216 FAUhdlc::doParse(void)
{
      this->symbolTable = new ast::BuiltinSymbolTable();
      yy::ParserDriver driver = yy::ParserDriver(*symbolTable);

      if (! this->freeStanding) {
            FAUhdlc::LibFile *lf = new FAUhdlc::LibFile();
            lf->filename = new std::string(
                              VHDL_DATA_DIR "/std_logic_1164.vhdl");
            lf->library = "ieee";
            this->sourceFiles.push_front(lf);
      }

      for (std::list<struct LibFile*>::const_iterator i = 
            this->sourceFiles.begin(); i != this->sourceFiles.end();
            i++) {
            
            try {
                  driver.parse(*((*i)->filename), (*i)->library);
            } catch (yy::SyntaxError e) {
                  if (ast::ErrorRegistry::hasErrors()) {
                        // don't report syntax errors, there are 
                        // other, probably more accute errors
                        this->resultCode = FAUHDLC_EXIT_ERROR;
                        return;
                  }

                  std::cerr << e.what() << std::endl;
                  this->resultCode = FAUHDLC_EXIT_ERROR;
                  return;
            } catch (std::runtime_error g) {
                  std::cerr << g.what() << std::endl;
                  this->resultCode = FAUHDLC_EXIT_EXCEPTION;
                  return;
            } catch (ast::CompileError h) {
                  std::cerr << "ERROR> " << h << std::endl;
            } catch (...) {
                  std::cerr << "unknown exception occured." 
                          << std::endl;
                  this->resultCode = FAUHDLC_EXIT_EXCEPTION;
                  return;
            }
      }
      this->topNode = driver.topNode;
      if (this->topNode == NULL) {
            this->resultCode = FAUHDLC_EXIT_EXCEPTION;
            return;
      }

      // dot graph after parsing?
      if (this->dotParse) {
#ifdef DEBUG
            std::cerr << "========= DOT VISITOR ==========" << std::endl;
#endif
            ast::DotVisitor v = ast::DotVisitor();
            this->topNode->accept(v);
            
            std::ofstream stream;
            stream.open(this->dotParseFile, std::ofstream::out);
            v.put(stream);
            stream.close();
      }
}

void
00281 FAUhdlc::putCompileMessages(void)
{
      // write warnings if any 
      if (ast::ErrorRegistry::hasWarnings()) {
            ast::ErrorRegistry::putWarnings(std::cerr);
      }

      // write errors if any
      if (ast::ErrorRegistry::hasErrors()) {
            ast::ErrorRegistry::putErrors(std::cerr);
            std::cerr << std::endl;
            this->resultCode = FAUHDLC_EXIT_ERROR;
      }
}

void
00297 FAUhdlc::doSemanticAnalysis(void)
{
#ifdef DEBUG
      std::cerr << "========= RESOLVE TYPES ==========" << std::endl;
#endif
      ast::ResolveTypes rt = ast::ResolveTypes(*this->symbolTable);
      this->topNode->accept(rt);

      if (ast::ErrorRegistry::hasErrors()) {
            return;
      }

#ifdef DEBUG
      std::cerr << "========= PROPAGATE CONSTANT ========" << std::endl;
#endif
      ast::ConstantPropagation cp = ast::ConstantPropagation();
      this->topNode->accept(cp);

      if (ast::ErrorRegistry::hasErrors()) {
            return;
      }

      if (this->dotConst) {
#ifdef DEBUG
            std::cerr << "========= DOT VISITOR ==========" << std::endl;
#endif
            ast::DotVisitor v = ast::DotVisitor();
            this->topNode->accept(v);
            
            std::ofstream stream;
            stream.open(this->dotConstFile, std::ofstream::out);
            v.put(stream);
            stream.close();
      }

#ifdef DEBUG
      std::cerr << "========= CHECK LOOPS ========" << std::endl;
#endif
      ast::CheckLoops cl = ast::CheckLoops();
      this->topNode->accept(cl);

      if (ast::ErrorRegistry::hasErrors()) {
            return;
      }

#ifdef DEBUG
      std::cerr << "========= NORMALIZE ASSOCS ========" << std::endl;
#endif
      ast::NormalizeAssocLists na = ast::NormalizeAssocLists();
      this->topNode->accept(na);

      if (ast::ErrorRegistry::hasErrors()) {
            return;
      }

#ifdef DEBUG
      std::cerr << "========= CHECK ACCESS MODE ========" << std::endl;
#endif
      ast::CheckAccessMode cam = ast::CheckAccessMode();
      this->topNode->accept(cam);

      if (ast::ErrorRegistry::hasErrors()) {
            return;
      }

#ifdef DEBUG
      std::cerr << "=========== WARN UNUSED ===========" << std::endl;
#endif
      ast::WarnUnused wuu = ast::WarnUnused();
      this->topNode->accept(wuu);

      if (ast::ErrorRegistry::hasErrors()) {
            return;
      }

#ifdef DEBUG
      std::cerr << "========= GATHER IMPLICITS ========" << std::endl;
#endif
      ast::GatherImplicits giv = ast::GatherImplicits();
      this->topNode->accept(giv);

      if (ast::ErrorRegistry::hasErrors()) {
            return;
      }

#ifdef DEBUG
      std::cerr << "========= SET PATH NAMES ==========" << std::endl;
#endif
      ast::SetPathName spn = ast::SetPathName();
      this->topNode->accept(spn);

      if (ast::ErrorRegistry::hasErrors()) {
            return;
      }

#ifdef DEBUG
      std::cerr << "========= CHECK WAIT CONDS ========" << std::endl;
#endif
      ast::WaitConditions cwc = ast::WaitConditions();
      this->topNode->accept(cwc);

      if (ast::ErrorRegistry::hasErrors()) {
            return;
      }


#ifdef DEBUG
      std::cerr << "========= GENERATE ICODE =========" << std::endl;
#endif
      ast::GenCode gc = ast::GenCode();
      this->topNode->accept(gc);

      if (ast::ErrorRegistry::hasErrors()) {
            return;
      }

      this->iTopNode = gc.container;
}

void
00417 FAUhdlc::doIntermediateTransform(void)
{
      // output code to file?
      if (this->outputFile == NULL) {
            return;
      }

      std::ofstream out;
      out.open(this->outputFile, std::ofstream::out);
      if (! out.good()) {
            out.close();
            std::cerr << "Couldn't open " << this->outputFile 
                  << " for writing." << std::endl;
            return;
      }
      intermediate::PrintCode pc = intermediate::PrintCode(out);

      assert(this->iTopNode != NULL);
      this->iTopNode->accept(pc);
      out.close();
}

void
00440 FAUhdlc::usage(std::ostream &out) const
{
      out << "FAUhdlc a VHDL to C compiler" << std::endl;
      out << std::endl;
      out << "Usage: fauhdlc [OPTIONS] files" << std::endl;
      out << "OPTIONS:" << std::endl;

      out << "\t--help              \tDisplay this help." << std::endl;
      out << "\t-o filaneme       "
            << "\tOutput to file filename." 
            << std::endl;

      out << "\t--parse-only       "
            << "\tstop with semantic analysis after parsing." 
            << std::endl;

      out << "\t--dot-parse=filename"
            << "\tCreate a dot-file called filename after parsing." 
            << std::endl;

      out << "\t--dot-const=filename"
            << "\tCreate a dot-file called filename after const. propagation."
            << std::endl;

      out << "\t--lib=library       "
          << "\tAll following files belong to library." 
            << std::endl;
      
      out << "\t-Werror            "
          << "\tReport warnings as errors."
          << std::endl;

      out << "\t--freestanding     "
          << "\tFreestanding mode (don't load std_logic)."
          << std::endl;

      out << std::endl;

      out << "For each source file, a separate library may be specified."
            << std::endl;
      out << "If no library has been specified, 'work' will be used." 
          << std::endl;

      out << std::endl;
      out << "Exit codes:" << std::endl;
      out << "\t1\twrong command line parameters." << std::endl;
      out << "\t3\tcompile error was found failed." << std::endl;
      out << "\t4\tOther exception occurred." << std::endl;
      out << std::endl;
}



}; /* namespace compiler */

int
main(int argc, char** argv) 
{
      util::GarbageCollect::initialize();
      compiler::FAUhdlc fauhdlc = compiler::FAUhdlc();
      fauhdlc.parseCmdLine(argc, argv);

      return fauhdlc.run();
}

Generated by  Doxygen 1.6.0   Back to index