Example #1
0
/*==============================================================================
 * FUNCTION:		CfgTest::testRenameVars
 * OVERVIEW:		Test the renaming of variables
 *============================================================================*/
void CfgTest::testRenameVars ()
{
  BinaryFileFactory bff;
  BinaryFile* pBF = bff.Load(FRONTIER_PENTIUM);
  CPPUNIT_ASSERT(pBF != 0);
  Prog* prog = new Prog;
  FrontEnd* pFE = new PentiumFrontEnd(pBF, prog, &bff);
  Type::clearNamedTypes();
  prog->setFrontEnd(pFE);
  pFE->decode(prog);

  UserProc* pProc = (UserProc*) prog->getProc(0);
  Cfg* cfg = pProc->getCFG();
  DataFlow* df = pProc->getDataFlow();

  // Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8]
  prog->finishDecode();

  df->dominators(cfg);
  df->placePhiFunctions(pProc);
  pProc->numberStatements();				// After placing phi functions!
  df->renameBlockVars(pProc, 0, 1);		// Block 0, mem depth 1

  // MIKE: something missing here?

  delete pFE;
}
Example #2
0
/**
 * Test the renaming of variables.
 */
void
CfgTest::testRenameVars()
{
	auto prog = Prog::open(FRONTIER_PENTIUM);
	CPPUNIT_ASSERT(prog);

	auto fe = prog->getFrontEnd();
	Type::clearNamedTypes();
	fe->decode();

	UserProc *pProc = (UserProc *)prog->getProc(0);
	Cfg *cfg = pProc->getCFG();
	DataFlow *df = pProc->getDataFlow();

	// Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8]
	prog->finishDecode();

	df->dominators(cfg);
	df->placePhiFunctions(pProc);
	pProc->numberStatements();         // After placing phi functions!
	df->renameBlockVars(pProc, 0, 1);  // Block 0, mem depth 1

	// MIKE: something missing here?

	delete prog;
}
Example #3
0
/**
 * Test the placing of phi functions.
 */
void
CfgTest::testPlacePhi()
{
	auto prog = Prog::open(FRONTIER_PENTIUM);
	CPPUNIT_ASSERT(prog);

	auto fe = prog->getFrontEnd();
	Type::clearNamedTypes();
	fe->decode();

	UserProc *pProc = (UserProc *)prog->getProc(0);
	Cfg *cfg = pProc->getCFG();

	// Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8]
	prog->finishDecode();

	DataFlow *df = pProc->getDataFlow();
	df->dominators(cfg);
	df->placePhiFunctions(pProc);

	// m[r29 - 8] (x for this program)
	Exp *e = Location::memOf(
	    new Binary(opMinus,
	        Location::regOf(29),
	        new Const(4)));

	// A_phi[x] should be the set {7 8 10 15 20 21} (all the join points)
	std::ostringstream ost;
	std::set<int> &A_phi = df->getA_phi(e);
	for (const auto &ii : A_phi)
		ost << ii << " ";
	std::string expected("7 8 10 15 20 21 ");
	CPPUNIT_ASSERT_EQUAL(expected, ost.str());
	delete prog;
}
Example #4
0
/**
 * Test the dominator frontier code.
 */
void
CfgTest::testDominators()
{
#define FRONTIER_FOUR     0x08048347
#define FRONTIER_FIVE     0x08048351
#define FRONTIER_TWELVE   0x080483b2
#define FRONTIER_THIRTEEN 0x080483b9

	auto prog = Prog::open(FRONTIER_PENTIUM);
	CPPUNIT_ASSERT(prog);

	auto fe = prog->getFrontEnd();
	Type::clearNamedTypes();
	fe->decode();

	bool gotMain;
	ADDRESS addr = fe->getMainEntryPoint(gotMain);
	CPPUNIT_ASSERT(addr != NO_ADDRESS);

	UserProc *pProc = (UserProc *)prog->getProc(0);
	Cfg *cfg = pProc->getCFG();
	DataFlow *df = pProc->getDataFlow();
	df->dominators(cfg);

	// Find BB "5" (as per Appel, Figure 19.5).
	BasicBlock *bb = nullptr;
	for (const auto &b : *cfg) {
		if (b->getLowAddr() == FRONTIER_FIVE) {
			bb = b;
			break;
		}
	}
	CPPUNIT_ASSERT(bb);

	std::ostringstream expected, actual;
#if 0
	expected << std::hex
	         << FRONTIER_FIVE << " "
	         << FRONTIER_THIRTEEN << " "
	         << FRONTIER_TWELVE << " "
	         << FRONTIER_FOUR << " "
	         << std::dec;
#endif
	expected << std::hex
	         << FRONTIER_THIRTEEN << " "
	         << FRONTIER_FOUR << " "
	         << FRONTIER_TWELVE << " "
	         << FRONTIER_FIVE << " "
	         << std::dec;
	int n5 = df->pbbToNode(bb);
	std::set<int> &DFset = df->getDF(n5);
	for (const auto &ii : DFset)
		actual << std::hex << (unsigned)df->nodeToBB(ii)->getLowAddr() << std::dec << " ";
	CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str());
	delete prog;
}
Example #5
0
/*==============================================================================
 * FUNCTION:		CfgTest::testPlacePhi2
 * OVERVIEW:		Test a case where a phi function is not needed
 *============================================================================*/
void CfgTest::testPlacePhi2 ()
{
  BinaryFileFactory bff;
  BinaryFile* pBF = bff.Load(IFTHEN_PENTIUM);
  CPPUNIT_ASSERT(pBF != 0);
  Prog* prog = new Prog;
  FrontEnd* pFE = new PentiumFrontEnd(pBF, prog, &bff);
  Type::clearNamedTypes();
  prog->setFrontEnd(pFE);
  pFE->decode(prog);

  UserProc* pProc = (UserProc*) prog->getProc(0);
  Cfg* cfg = pProc->getCFG();
  DataFlow* df = pProc->getDataFlow();

  // Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8]
  prog->finishDecode();

  df->dominators(cfg);
  df->placePhiFunctions(pProc);

  // In this program, x is allocated at [ebp-4], a at [ebp-8], and
  // b at [ebp-12]
  // We check that A_phi[ m[ebp-8] ] is 4, and that
  // A_phi A_phi[ m[ebp-8] ] is null
  // (block 4 comes out with n=4)

  std::string expected = "4 ";
  std::ostringstream actual;
  // m[r29 - 8]
  Exp* e = new Unary(opMemOf,
                     new Binary(opMinus,
                                Location::regOf(29),
                                new Const(8)));
  std::set<int>& s = df->getA_phi(e);
  std::set<int>::iterator pp;
  for (pp = s.begin(); pp != s.end(); pp++)
    actual << *pp << " ";
  CPPUNIT_ASSERT_EQUAL(expected, actual.str());
  delete e;

  expected = "";
  std::ostringstream actual2;
  // m[r29 - 12]
  e = new Unary(opMemOf,
                new Binary(opMinus,
                           Location::regOf(29),
                           new Const(12)));

  std::set<int>& s2 = df->getA_phi(e);
  for (pp = s2.begin(); pp != s2.end(); pp++)
    actual2 << *pp << " ";
  CPPUNIT_ASSERT_EQUAL(expected, actual2.str());
  delete e;
  delete pFE;
}
Example #6
0
/**
 * Test a case where a phi function is not needed.
 */
void
CfgTest::testPlacePhi2()
{
	auto prog = Prog::open(IFTHEN_PENTIUM);
	CPPUNIT_ASSERT(prog);

	auto fe = prog->getFrontEnd();
	Type::clearNamedTypes();
	fe->decode();

	UserProc *pProc = (UserProc *)prog->getProc(0);
	Cfg *cfg = pProc->getCFG();
	DataFlow *df = pProc->getDataFlow();

	// Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8]
	prog->finishDecode();

	df->dominators(cfg);
	df->placePhiFunctions(pProc);

	// In this program, x is allocated at [ebp-4], a at [ebp-8], and
	// b at [ebp-12]
	// We check that A_phi[ m[ebp-8] ] is 4, and that
	// A_phi A_phi[ m[ebp-8] ] is null
	// (block 4 comes out with n=4)

	std::string expected = "4 ";
	std::ostringstream actual;
	// m[r29 - 8]
	Exp *e = Location::memOf(
	    new Binary(opMinus,
	        Location::regOf(29),
	        new Const(8)));
	std::set<int> &s = df->getA_phi(e);
	for (const auto &pp : s)
		actual << pp << " ";
	CPPUNIT_ASSERT_EQUAL(expected, actual.str());
	delete e;

	expected = "";
	std::ostringstream actual2;
	// m[r29 - 12]
	e = Location::memOf(
	    new Binary(opMinus,
	        Location::regOf(29),
	        new Const(12)));

	std::set<int> &s2 = df->getA_phi(e);
	for (const auto &pp : s2)
		actual2 << pp << " ";
	CPPUNIT_ASSERT_EQUAL(expected, actual2.str());
	delete e;
	delete prog;
}
Example #7
0
/**
 * Test a case where semi dominators are different to dominators.
 */
void
CfgTest::testSemiDominators()
{
#define SEMI_L  0x80483b0
#define SEMI_M  0x80483e2
#define SEMI_B  0x8048345
#define SEMI_D  0x8048354
#define SEMI_M  0x80483e2

	auto prog = Prog::open(SEMI_PENTIUM);
	CPPUNIT_ASSERT(prog);

	auto fe = prog->getFrontEnd();
	Type::clearNamedTypes();
	fe->decode();

	bool gotMain;
	ADDRESS addr = fe->getMainEntryPoint(gotMain);
	CPPUNIT_ASSERT(addr != NO_ADDRESS);

	UserProc *pProc = (UserProc *)prog->getProc(0);
	Cfg *cfg = pProc->getCFG();

	DataFlow *df = pProc->getDataFlow();
	df->dominators(cfg);

	// Find BB "L (6)" (as per Appel, Figure 19.8).
	BasicBlock *bb = nullptr;
	for (const auto &b : *cfg) {
		if (b->getLowAddr() == SEMI_L) {
			bb = b;
			break;
		}
	}
	CPPUNIT_ASSERT(bb);
	int nL = df->pbbToNode(bb);

	// The dominator for L should be B, where the semi dominator is D
	// (book says F)
	unsigned actual_dom  = (unsigned)df->nodeToBB(df->getIdom(nL))->getLowAddr();
	unsigned actual_semi = (unsigned)df->nodeToBB(df->getSemi(nL))->getLowAddr();
	CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_B, actual_dom);
	CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_D, actual_semi);
	// Check the final dominator frontier as well; should be M and B
	std::ostringstream expected, actual;
#if 0
	expected << std::hex << SEMI_M << " " << SEMI_B << " " << std::dec;
#endif
	expected << std::hex << SEMI_B << " " << SEMI_M << " " << std::dec;
	std::set<int> &DFset = df->getDF(nL);
	for (const auto &ii : DFset)
		actual << std::hex << (unsigned)df->nodeToBB(ii)->getLowAddr() << std::dec << " ";
	CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str());
	delete prog;
}
Example #8
0
void CfgTest::testDominators ()
{
  BinaryFileFactory bff;
  BinaryFile *pBF = bff.Load(FRONTIER_PENTIUM);
  CPPUNIT_ASSERT(pBF != 0);
  Prog* prog = new Prog;
  FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
  Type::clearNamedTypes();
  prog->setFrontEnd(pFE);
  pFE->decode(prog);

  bool gotMain;
  ADDRESS addr = pFE->getMainEntryPoint(gotMain);
  CPPUNIT_ASSERT (addr != NO_ADDRESS);

  UserProc* pProc = (UserProc*) prog->getProc(0);
  Cfg* cfg = pProc->getCFG();
  DataFlow* df = pProc->getDataFlow();
  df->dominators(cfg);

  // Find BB "5" (as per Appel, Figure 19.5).
  BB_IT it;
  PBB bb = cfg->getFirstBB(it);
  while (bb && bb->getLowAddr() != FRONTIER_FIVE)
    {
      bb = cfg->getNextBB(it);
    }
  CPPUNIT_ASSERT(bb);

  std::ostringstream expected, actual;
  //expected << std::hex << FRONTIER_FIVE << " " << FRONTIER_THIRTEEN << " " << FRONTIER_TWELVE << " " <<
  //	FRONTIER_FOUR << " ";
  expected << std::hex << FRONTIER_THIRTEEN << " " << FRONTIER_FOUR << " " << FRONTIER_TWELVE << " " <<
  FRONTIER_FIVE << " ";
  int n5 = df->pbbToNode(bb);
  std::set<int>::iterator ii;
  std::set<int>& DFset = df->getDF(n5);
  for (ii=DFset.begin(); ii != DFset.end(); ii++)
    actual << std::hex << (unsigned)df->nodeToBB(*ii)->getLowAddr() << " ";
  CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str());

  pBF->UnLoad();
  delete pFE;
}
Example #9
0
	/*!
	 * \brief Constructor
	 * \param procedure Procedure to analyze
	 */
	LiveVariables::LiveVariables(const IR::Procedure &procedure, const FlowGraph &flowGraph)
		: mProcedure(procedure)
	{
		Util::Timer timer;
		timer.start();

		// Construct the set of all variables in the procedure
		std::set<const IR::Symbol*> all;
		for(const std::unique_ptr<IR::Symbol> &symbol : mProcedure.symbols()) {
			all.insert(symbol.get());
		}

		// Construct gen/kill sets for data flow analysis.
		std::map<const IR::Entry*, std::set<const IR::Symbol*>> gen;
		std::map<const IR::Entry*, std::set<const IR::Symbol*>> kill;
		for(const IR::Entry *entry : mProcedure.entries()) {
			for(const IR::Symbol *symbol : all) {
				std::set<const IR::Symbol*> &g = gen[entry];
				if(entry->uses(symbol)) {
					// An entry which uses a symbol adds that symbol to the set of live symbols
					g.insert(symbol);
				}

				const IR::Symbol *assign = entry->assign();
				if(assign && g.find(assign) == g.end()) {
					// An entry which assigns to a symbol and does not use it kills that symbol
					// from the live symbol set
					kill[entry].insert(assign);
				}
			}
		}

		// Perform a backwards data flow analysis on the procedure, using the gen and kill sets
		// constructed above.
		DataFlow<const IR::Symbol*> dataFlow;
		mMap = dataFlow.analyze(flowGraph, gen, kill, all, DataFlow<const IR::Symbol*>::Meet::Union, DataFlow<const IR::Symbol*>::Direction::Backward);

		Util::log("opt.time") << "  LiveVariables(" << mProcedure.name() << "): " << timer.stop() << "ms" << std::endl;
	}
Example #10
0
void CfgTest::testSemiDominators ()
{
  BinaryFileFactory bff;
  BinaryFile* pBF = bff.Load(SEMI_PENTIUM);
  CPPUNIT_ASSERT(pBF != 0);
  Prog* prog = new Prog;
  FrontEnd* pFE = new PentiumFrontEnd(pBF, prog, &bff);
  Type::clearNamedTypes();
  prog->setFrontEnd(pFE);
  pFE->decode(prog);

  bool gotMain;
  ADDRESS addr = pFE->getMainEntryPoint(gotMain);
  CPPUNIT_ASSERT (addr != NO_ADDRESS);

  UserProc* pProc = (UserProc*) prog->getProc(0);
  Cfg* cfg = pProc->getCFG();

  DataFlow* df = pProc->getDataFlow();
  df->dominators(cfg);

  // Find BB "L (6)" (as per Appel, Figure 19.8).
  BB_IT it;
  PBB bb = cfg->getFirstBB(it);
  while (bb && bb->getLowAddr() != SEMI_L)
    {
      bb = cfg->getNextBB(it);
    }
  CPPUNIT_ASSERT(bb);
  int nL = df->pbbToNode(bb);

  // The dominator for L should be B, where the semi dominator is D
  // (book says F)
  unsigned actual_dom	 = (unsigned)df->nodeToBB(df->getIdom(nL))->getLowAddr();
  unsigned actual_semi = (unsigned)df->nodeToBB(df->getSemi(nL))->getLowAddr();
  CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_B, actual_dom);
  CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_D, actual_semi);
  // Check the final dominator frontier as well; should be M and B
  std::ostringstream expected, actual;
  //expected << std::hex << SEMI_M << " " << SEMI_B << " ";
  expected << std::hex << SEMI_B << " " << SEMI_M << " ";
  std::set<int>::iterator ii;
  std::set<int>& DFset = df->getDF(nL);
  for (ii=DFset.begin(); ii != DFset.end(); ii++)
    actual << std::hex << (unsigned)df->nodeToBB(*ii)->getLowAddr() << " ";
  CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str());
  delete pFE;
}
Example #11
0
/*==============================================================================
 * FUNCTION:		CfgTest::testPlacePhi
 * OVERVIEW:		Test the placing of phi functions
 *============================================================================*/
void CfgTest::testPlacePhi ()
{
  BinaryFileFactory bff;
  BinaryFile* pBF = bff.Load(FRONTIER_PENTIUM);
  CPPUNIT_ASSERT(pBF != 0);
  Prog* prog = new Prog;
  FrontEnd* pFE = new PentiumFrontEnd(pBF, prog, &bff);
  Type::clearNamedTypes();
  prog->setFrontEnd(pFE);
  pFE->decode(prog);

  UserProc* pProc = (UserProc*) prog->getProc(0);
  Cfg* cfg = pProc->getCFG();

  // Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8]
  prog->finishDecode();

  DataFlow* df = pProc->getDataFlow();
  df->dominators(cfg);
  df->placePhiFunctions(pProc);

  // m[r29 - 8] (x for this program)
  Exp* e = new Unary(opMemOf,
                     new Binary(opMinus,
                                Location::regOf(29),
                                new Const(4)));

  // A_phi[x] should be the set {7 8 10 15 20 21} (all the join points)
  std::ostringstream ost;
  std::set<int>::iterator ii;
  std::set<int>& A_phi = df->getA_phi(e);
  for (ii = A_phi.begin(); ii != A_phi.end(); ++ii)
    ost << *ii << " ";
  std::string expected("7 8 10 15 20 21 ");
  CPPUNIT_ASSERT_EQUAL(expected, ost.str());
  delete pFE;
}
Example #12
0
void Generator<Annotation, Runtime, Driver>::generate(
  const LoopTrees<Annotation> & loop_trees,
  std::set<std::list<Kernel<Annotation, Runtime> *> > & kernel_lists,
  LoopMapper<Annotation, Runtime> & loop_mapper,
  LoopTiler<Annotation, Runtime> & loop_tiler,
  DataFlow<Annotation, Runtime> & data_flow
) {
  typedef typename LoopTrees<Annotation>::loop_t loop_t;
  typedef typename LoopTiler<Annotation, Runtime>::loop_tiling_t loop_tiling_t;
  typedef Kernel<Annotation, Runtime> Kernel;

  typename std::set<std::list<Kernel *> >::const_iterator it_kernel_list;
  typename std::list<Kernel *>::const_iterator it_kernel;

  typename DataFlow<Annotation, Runtime>::context_t df_ctx;

  // 0 - init data flow

  data_flow.createContextFromLoopTree(loop_trees, df_ctx);
  data_flow.markSplittedData(df_ctx);

  // 1 - Loop Selection : Generate multiple list of kernel that implement the given LoopTree

  loop_mapper.createKernels(loop_trees, kernel_lists);

  // 2 - Data Flow : performs data-flow analysis for each list of kernel

  for (it_kernel_list = kernel_lists.begin(); it_kernel_list != kernel_lists.end(); it_kernel_list++)
    data_flow.generateFlowSets(*it_kernel_list, df_ctx);

  // 3 - Arguments : determines the list of arguments needed by each kernel

  for (it_kernel_list = kernel_lists.begin(); it_kernel_list != kernel_lists.end(); it_kernel_list++)
    for (it_kernel = it_kernel_list->begin(); it_kernel != it_kernel_list->end(); it_kernel++)
      buildArgumentLists(loop_trees, *it_kernel);

  for (it_kernel_list = kernel_lists.begin(); it_kernel_list != kernel_lists.end(); it_kernel_list++)
    for (it_kernel = it_kernel_list->begin(); it_kernel != it_kernel_list->end(); it_kernel++) {

      // 4 - Iterations Mapping : determines the "shape" of every loop of each kernel.
      //     The "shape" of a loop is how this loop is adapted to the execution model.

      std::map<loop_t *, std::vector<loop_tiling_t *> > tiling_map;

      loop_tiler.determineTiles(*it_kernel, tiling_map);

      std::set<std::map<loop_t *, loop_tiling_t *> > loop_tiling_set;
      buildAllTileConfigs<Annotation, Runtime>(
        std::map<loop_t *, loop_tiling_t *>(),
        tiling_map.begin(),
        tiling_map.end(),
        loop_tiling_set
      );

      // 5 - Code Generation

      size_t cnt = 0;
      typename std::set<std::map<loop_t *, loop_tiling_t *> >::iterator it_loop_tiling_map;
      for (it_loop_tiling_map = loop_tiling_set.begin(); it_loop_tiling_map != loop_tiling_set.end(); it_loop_tiling_map++) {
        typename ::MFB::KLT<Kernel>::object_desc_t kernel_desc(cnt++, *it_kernel, p_file_id);

        kernel_desc.tiling.insert(it_loop_tiling_map->begin(), it_loop_tiling_map->end());

        typename Kernel::kernel_desc_t * kernel = p_driver.template build<Kernel>(kernel_desc);

        (*it_kernel)->addKernel(kernel);
      }
      typename std::map<loop_t *, std::vector<loop_tiling_t *> >::const_iterator it_tiling_vect;
      typename std::vector<loop_tiling_t *>::const_iterator it_tiling;
      for (it_tiling_vect = tiling_map.begin(); it_tiling_vect != tiling_map.end(); it_tiling_vect++)
        for (it_tiling = it_tiling_vect->second.begin(); it_tiling != it_tiling_vect->second.end(); it_tiling++)
          delete *it_tiling;
      
    }
}
int main(int argc, char **argv)
{
    int exitcode = 0;
    const char* progname = argv[0];

    // build option parser
    void* argtable[] = {
        h = arg_lit0("h","help", "print this help and exit"),
        version = arg_lit0("v","version", "print version information and exit"),
        verbose = arg_lit0(NULL, "verbose", "more logs"),
        l = arg_lit0("l", NULL, "list all available components"),
        d = arg_str0("d","describe","component", "Describe a component, show its parameters"),
        datablock = arg_int0("s",NULL, "datablocksize", "prefered data block size"),
        libs = arg_strn("x","loadlibrary","libnames",0,10,"yaafe component library name to load."),
        dataflow = arg_file0("c",NULL,"file","dataflow to process"),
        format = arg_str0("o", NULL,"format","output format, see available output formats below."),
        formatparams = arg_strn("p", NULL,"key=value",0,10,"output format parameters (see below)"),
        outdir = arg_str0("b", NULL,"dir","output base directory"),
        files = arg_filen(NULL,NULL,"FILES",0,argc,"audio files to process"),
        the_end = arg_end(20)
    };

    int nerrors = arg_parse(argc, argv, argtable);

    /* special case: '--help' takes precedence over error reporting */
    if (h->count > 0)
    {
        printf("%s is a dataflow processing engine\n", progname);
        printf("\n");
        printf("Usage: %s", progname);
        arg_print_syntax(stdout,argtable,"\n");
        arg_print_glossary(stdout,argtable, " %-25s %s\n");
        printf("\n");
        exitcode = ComponentFactory::instance()->loadLibrary("yaafe-io");
        if (exitcode) {
            printf("error while loading yaafe-io library !\n");
        } else {
            printOutputFormats();
            exitcode = 0;
        }
        goto exit;
    }

    /* special case: '--version' takes precedence error reporting */
    if (version->count > 0)
    {
        printf("%s version %s\n", progname, ComponentFactory::version());
        exitcode = 0;
        goto exit;
    }

    /* If the parser returned any errors then display them and exit */
    if (nerrors > 0)
    {
        /* Display the error details contained in the arg_end struct.*/
        arg_print_errors(stdout,the_end, progname);
        printf("Try '%s --help' for more information.\n", progname);
        exitcode = 1;
        goto exit;
    }

    if (verbose->count)
        verboseFlag = true;

    if (datablock->count)
        DataBlock::setPreferedBlockSize(datablock->ival[0]);

    // register io components
    exitcode = ComponentFactory::instance()->loadLibrary("yaafe-io");
    if (exitcode)
        goto exit;

    // register given dynamic libraries
    for (int i=0; i<libs->count; i++)
    {
        exitcode = ComponentFactory::instance()->loadLibrary(libs->sval[i]);
        if (exitcode)
            goto exit;
    }

    if (l->count)
    {
        listComponents();
        goto exit;
    }
    if (d->count)
    {
        describeComponent(d->sval[0]);
        goto exit;
    }


    if (files->count)
    {
        if (!dataflow->count) {
            cerr << "ERROR: please specify a dataflow file with -c option !" << endl;
            exitcode = -1;
            goto exit;
        }

        DataFlow df;
        if (!df.load(dataflow->filename[0])) {
            cerr << "ERROR: cannot load dataflow from file " << dataflow->filename[0] << endl;
            exitcode = -1;
            goto exit;
        }

        Engine engine;
        if (!engine.load(df)) {
            cerr << "ERROR: cannot initialize dataflow engine" << endl;
            exitcode = -1;
            goto exit;
        }

        AudioFileProcessor processor;
        {
            string formatStr = "csv";
            if (format->count)
                formatStr = format->sval[0];
            string outDirStr = "";
            if (outdir->count)
                outDirStr = outdir->sval[0];
            ParameterMap params;
            for (int p=0; p<formatparams->count; p++) {
                string str = formatparams->sval[p];
                size_t keyEnd = str.find('=');
                if (keyEnd==string::npos) {
                    cerr << "Malformed parameter " << formatparams->sval[p] << endl;
                    continue;
                }
                params[str.substr(0,keyEnd)] = str.substr(keyEnd+1,str.size()-keyEnd-1);
            }
            if (!processor.setOutputFormat(formatStr,outDirStr,params)) {
                exitcode = -1;
                goto exit;
            }
        }

        for (int i=0; i<files->count; i++)
        {
            int res = processor.processFile(engine, files->filename[i]);
            if (res!=0) {
                cerr << "ERROR: error while processing " << files->filename[i] << endl;
            }
        }
    }

#ifdef WITH_TIMERS
    Timer::print_all_timers();
#endif

exit:
    // release components to avoid definitly lost blocks in valgrind
    ComponentFactory::destroy();
    /* deallocate each non-null entry in argtable[] */
    arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));

    return exitcode;
}