Exemple #1
0
void CombinedPass::do_file_set_block( FileSetBlock* file_set_block ) {
    list<SymbolTable*> file_scope_tables;

    for (Iter<FileBlock*> iter = file_set_block->get_file_block_iterator();
	 iter.is_valid(); iter.next()) 
      {
	file_scope_tables.push_back(iter.current()->get_symbol_table());
      }
    file_scope_tables.push_back(file_set_block->get_file_set_symbol_table());
    
    CollisionAvoider walker(get_suif_env(),
			    file_set_block->get_external_symbol_table(),
			    &file_scope_tables,
                            (file_set_block->get_file_block(0))->
                                get_source_file_name(),
			    true);
    file_set_block->walk(walker);
    }
Exemple #2
0
/* return true if the symbol has a name crash with another symbol in
 * its parent (a symbol table).
 * This implementation just consider name crashes and ignore the symbol
 * type.
 */
static bool is_var_name_crashd_locally(const Symbol* symbol)
{
  LString sname = symbol->get_name();
  if (sname == emptyLString) return false;
  SymbolTable* symtab = to<SymbolTable>(symbol->get_parent());
  if (!is_kind_of<VariableSymbol>(symbol)) return false;
  for (Iter<SymbolTableObject*> iter = 
	 symtab->get_symbol_table_object_iterator();
       iter.is_valid();
       iter.next()) {
    if (symbol == const_cast<const SymbolTableObject*>(iter.current()))
      continue;
    if (!is_kind_of<VariableSymbol>(iter.current())) continue;
    if (iter.current()->get_name() == sname) {
      return true;
    }
  }
  return false;
}
Exemple #3
0
void InstanceFieldsLayoutPass::mangle_fields( ClassType* ctype ) {
  BasicSymbolTable* symtab =
    ctype->get_group_symbol_table();
  Iter<SymbolTableObject*> iter =
    symtab->get_symbol_table_object_iterator();

  while( iter.is_valid() ) {
    InstanceFieldSymbol* fsym =
      to<InstanceFieldSymbol>( iter.current() );

    if ( _verbose ) {
      //      cout << fsym->get_name().c_str() << " -> "
      //	   << mangled_name(fsym).c_str() << endl;
    }

    symtab->change_name( fsym, mangled_name(fsym) );
    iter.next();
  }
}
void form_worklist(Statement *s){

    if(!s) return;

    if(is_a<IfStatement>(s)){
       form_worklist((to<IfStatement>(s))->get_then_part());
       form_worklist((to<IfStatement>(s))->get_else_part());
       worklist->push_back(to<IfStatement>(s));
    }else if(is_a<CForStatement>(s))
       form_worklist((to<CForStatement>(s))->get_body());	
    else if(is_a<WhileStatement>(s))
       form_worklist((to<WhileStatement>(s))->get_body());	
    else if(is_a<ScopeStatement>(s))
       form_worklist((to<ScopeStatement>(s))->get_body());	
    else if(is_a<StatementList>(s))
       for(Iter<Statement*> iter = (to<StatementList>(s))->get_statement_iterator();
	   iter.is_valid(); iter.next())
	   form_worklist(iter.current());
    
}
Exemple #5
0
void 
M2c::process_sym_table(SymTable *st)
{
    bool st_is_private = is_private(st);

    Iter<SymbolTableObject*> iter = st->get_symbol_table_object_iterator();
    for (/* iter */; iter.is_valid(); iter.next()) {
	SymbolTableObject *the_sto = iter.current();
	if (is_kind_of<VariableSymbol>(the_sto)) {
	    if (is_kind_of<ParameterSymbol>(the_sto))
		continue;			// don't shadow an arg!

	    VarSym *v = to<VariableSymbol>(the_sto); 

	    if (!is_global(st)) {
		printer->print_var_def(v, false);
	    }
	    else if (v->get_definition() != NULL) {
		postponed_vars.push_back(v);
		printer->print_var_def(v, true);
	    }
	    else {
		claim(is_external(v));
		fprintf(out, "extern ");
		printer->print_sym_decl(v);
		fprintf(out, ";\n");
	    }
	} else if (is_kind_of<ProcedureSymbol>(the_sto)) {
	    if (st_is_private) fputs("static ", out);
	    printer->print_proc_decl(to<ProcedureSymbol>(the_sto));

	} else if (is_kind_of<Type>(the_sto)) {
	    if (is_kind_of<EnumeratedType>(the_sto) ||
		(is_kind_of<GroupType>(the_sto) &&
		 to<GroupType>(the_sto)->get_is_complete())) {
		printer->print_type(to<Type>(the_sto));
		fprintf(out, ";\n");
	    }
	}
    }
}
void CopyPropagationPass2::RemoveFromStatementList(StatementList* parent,
						   Statement* child)
{
  assert(parent != NULL) ;
  assert(child != NULL) ;

  // Find the position of statement and remove it
  int pos = 0 ; 
  Iter<Statement*> statementIter = parent->get_statement_iterator() ;
  while (statementIter.is_valid())
  {
    if (statementIter.current() == child)
    {
      break ;
    }
    statementIter.next() ;
    ++pos ;
  }

  assert(parent->get_statement(pos) == child) ;
  parent->remove_statement(pos) ;
}
Exemple #7
0
void
Summarize::initialize()
{
    DefinitionBlock *db = the_file_block->get_definition_block();

    max_event_id = 0;
    for (Iter<ProcedureDefinition*> iter = db-> get_procedure_definition_iterator();
	 iter.is_valid();
	 iter.next())
    {
	OptUnit *unit = iter.current();
	claim(is_kind_of<Cfg>(get_body(unit)), "Body is not in CFG form");
	Cfg *unit_cfg = static_cast<Cfg*>(get_body(unit));
	debug(5, "Procedure %s", get_name(unit).chars());
	if_debug(5)
	    fprint(stdout, unit_cfg, true, true); // layout and code

	for (int i = 0; i < nodes_size(unit_cfg); ++i)
	{
	    CfgNode *block = get_node(unit_cfg, i);
	    for (InstrHandle h = start(block); h != end(block); ++h)
		if (HaltLabelNote note = get_note(*h, k_halt))
		    switch (note.get_kind())
		    {
		      case halt::CBR:
		      case halt::MBR:
		      case halt::ENTRY:
		      case halt::EXIT:
		      {
			  long id = note.get_unique_id();
			  if (max_event_id <= id)
			      max_event_id =  id + 1;
		      }
		    }
	}
    }
    fprintf(out, "%d\n", max_event_id);
}
//	now requires compact and ordered. 
static bool is_compact(MultiWayBranchStatement *the_case) {
    Iter<MultiWayBranchStatement::case_pair > iter = the_case->get_case_iterator();
    IInteger low;
    IInteger high;
    bool first = true;
    int count = 0;
    while (iter.is_valid()) {
        MultiWayBranchStatement::case_pair pair = iter.current();
	if (first) {
	    low =pair.first;
	    high = pair.first; 
	    first = false;
	    }
	else {
#ifdef COMPACT_ONLY
	    if (low > pair.first)
		low = pair.first;
	    if (high < pair.first)
		high = pair.first;
#else
	    if (pair.first < low)
		return false;
	    if (pair.first < high)
		return false;
	    high = pair.first;
#endif
	    }
	
	count ++;
	iter.next();
	}
    if (count == 0)
	return false;
    double density = (double)count / (high - low + 1).c_double();
    return density > 0.9999999999;
    }
Exemple #9
0
static
String handle_static_statement(CPrintStyleModule *state,
			       const SuifObject *obj)
{
  Statement *stmt = to<Statement>(obj);
  // Use the iterator over
  //    destination_vars
  //    source ops
  //    source variables
  // Use the iterator over source ops and
  // get the classname

  String return_str = "(";
  bool needs_comma = false;

  {for (Iter<VariableSymbol *> iter = stmt->get_destination_var_iterator();
       iter.is_valid();
       iter.next()) {
    VariableSymbol *var = iter.current();
    if (needs_comma) {
      return_str += ",";
    } else {
      needs_comma = true;
    }
    String op = state->print_to_string(var);
    return_str += op;
  }
  }
  return_str += ") = ";

  String opname = stmt->getClassName();
  return_str += String("?") + opname + "(";
  needs_comma = false;
  {for (Iter<Expression *> iter = stmt->get_source_op_iterator();
       iter.is_valid();
       iter.next()) {
    Expression *opn = iter.current();
    if (needs_comma) {
      return_str += ",";
    } else {
      needs_comma = true;
    }
    String op = state->print_to_string(opn);
    return_str += op;
  }}
  return_str += ")";

  needs_comma = false;
  {for (Iter<Statement *> iter = stmt->get_child_statement_iterator();
       iter.is_valid();
       iter.next()) {
    Statement *statement = iter.current();
    if (needs_comma) {
      return_str += "; ";
    } else {
      needs_comma = true;
    }
    String op = state->print_to_string(statement);
    return_str += op;
  }}
  return_str += ";";

  return(return_str);
}
Exemple #10
0
int tool_main(int argc, char** argv) {
    SetupCrashHandler();
    SkCommandLineFlags::Parse(argc, argv);
#if SK_ENABLE_INST_COUNT
    if (FLAGS_leaks) {
        gPrintInstCount = true;
    }
#endif
    SkAutoGraphics ag;

    // First, parse some flags.
    BenchLogger logger;
    if (FLAGS_logFile.count()) {
        logger.SetLogFile(FLAGS_logFile[0]);
    }

    LoggerResultsWriter logWriter(logger, FLAGS_timeFormat[0]);
    MultiResultsWriter writer;
    writer.add(&logWriter);

    SkAutoTDelete<JSONResultsWriter> jsonWriter;
    if (FLAGS_outResultsFile.count()) {
        jsonWriter.reset(SkNEW(JSONResultsWriter(FLAGS_outResultsFile[0])));
        writer.add(jsonWriter.get());
    }

    // Instantiate after all the writers have been added to writer so that we
    // call close() before their destructors are called on the way out.
    CallEnd<MultiResultsWriter> ender(writer);

    const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF;
    SkTriState::State dither = SkTriState::kDefault;
    for (size_t i = 0; i < 3; i++) {
        if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) {
            dither = static_cast<SkTriState::State>(i);
        }
    }

    BenchMode benchMode = kNormal_BenchMode;
    for (size_t i = 0; i < SK_ARRAY_COUNT(BenchMode_Name); i++) {
        if (strcmp(FLAGS_mode[0], BenchMode_Name[i]) == 0) {
            benchMode = static_cast<BenchMode>(i);
        }
    }

    SkTDArray<int> configs;
    bool runDefaultConfigs = false;
    // Try user-given configs first.
    for (int i = 0; i < FLAGS_config.count(); i++) {
        for (int j = 0; j < static_cast<int>(SK_ARRAY_COUNT(gConfigs)); ++j) {
            if (0 == strcmp(FLAGS_config[i], gConfigs[j].name)) {
                *configs.append() = j;
            } else if (0 == strcmp(FLAGS_config[i], kDefaultsConfigStr)) {
                runDefaultConfigs = true;
            }
        }
    }
    // If there weren't any, fill in with defaults.
    if (runDefaultConfigs) {
        for (int i = 0; i < static_cast<int>(SK_ARRAY_COUNT(gConfigs)); ++i) {
            if (gConfigs[i].runByDefault) {
                *configs.append() = i;
            }
        }
    }
    // Filter out things we can't run.
    if (kNormal_BenchMode != benchMode) {
        // Non-rendering configs only run in normal mode
        for (int i = 0; i < configs.count(); ++i) {
            const Config& config = gConfigs[configs[i]];
            if (Benchmark::kNonRendering_Backend == config.backend) {
                configs.remove(i, 1);
                --i;
            }
        }
    }

#if SK_SUPPORT_GPU
    for (int i = 0; i < configs.count(); ++i) {
        const Config& config = gConfigs[configs[i]];

        if (Benchmark::kGPU_Backend == config.backend) {
            GrContext* context = gContextFactory.get(config.contextType);
            if (NULL == context) {
                SkDebugf("GrContext could not be created for config %s. Config will be skipped.\n",
                    config.name);
                configs.remove(i);
                --i;
                continue;
            }
            if (config.sampleCount > context->getMaxSampleCount()){
                SkDebugf(
                    "Sample count (%d) for config %s is not supported. Config will be skipped.\n",
                    config.sampleCount, config.name);
                configs.remove(i);
                --i;
                continue;
            }
        }
    }
#endif

    // All flags should be parsed now.  Report our settings.
    if (FLAGS_runOnce) {
        logger.logError("bench was run with --runOnce, so we're going to hide the times."
                        " It's for your own good!\n");
    }
    writer.option("mode", FLAGS_mode[0]);
    writer.option("alpha", SkStringPrintf("0x%02X", alpha).c_str());
    writer.option("antialias", SkStringPrintf("%d", FLAGS_forceAA).c_str());
    writer.option("filter", SkStringPrintf("%d", FLAGS_forceFilter).c_str());
    writer.option("dither",  SkTriState::Name[dither]);

    writer.option("rotate", SkStringPrintf("%d", FLAGS_rotate).c_str());
    writer.option("scale", SkStringPrintf("%d", FLAGS_scale).c_str());
    writer.option("clip", SkStringPrintf("%d", FLAGS_clip).c_str());

#if defined(SK_BUILD_FOR_WIN32)
    writer.option("system", "WIN32");
#elif defined(SK_BUILD_FOR_MAC)
    writer.option("system", "MAC");
#elif defined(SK_BUILD_FOR_ANDROID)
    writer.option("system", "ANDROID");
#elif defined(SK_BUILD_FOR_UNIX)
    writer.option("system", "UNIX");
#else
    writer.option("system", "other");
#endif

#if defined(SK_DEBUG)
    writer.option("build", "DEBUG");
#else
    writer.option("build", "RELEASE");
#endif

    // Set texture cache limits if non-default.
    for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
#if SK_SUPPORT_GPU
        const Config& config = gConfigs[i];
        if (Benchmark::kGPU_Backend != config.backend) {
            continue;
        }
        GrContext* context = gContextFactory.get(config.contextType);
        if (NULL == context) {
            continue;
        }

        size_t bytes;
        int count;
        context->getResourceCacheLimits(&count, &bytes);
        if (-1 != FLAGS_gpuCacheBytes) {
            bytes = static_cast<size_t>(FLAGS_gpuCacheBytes);
        }
        if (-1 != FLAGS_gpuCacheCount) {
            count = FLAGS_gpuCacheCount;
        }
        context->setResourceCacheLimits(count, bytes);
#endif
    }

    // Run each bench in each configuration it supports and we asked for.
    Iter iter;
    Benchmark* bench;
    while ((bench = iter.next()) != NULL) {
        SkAutoTUnref<Benchmark> benchUnref(bench);
        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
            continue;
        }

        bench->setForceAlpha(alpha);
        bench->setForceAA(FLAGS_forceAA);
        bench->setForceFilter(FLAGS_forceFilter);
        bench->setDither(dither);
        bench->preDraw();

        bool loggedBenchName = false;
        for (int i = 0; i < configs.count(); ++i) {
            const int configIndex = configs[i];
            const Config& config = gConfigs[configIndex];

            if (!bench->isSuitableFor(config.backend)) {
                continue;
            }

            GrContext* context = NULL;
#if SK_SUPPORT_GPU
            SkGLContextHelper* glContext = NULL;
            if (Benchmark::kGPU_Backend == config.backend) {
                context = gContextFactory.get(config.contextType);
                if (NULL == context) {
                    continue;
                }
                glContext = gContextFactory.getGLContext(config.contextType);
            }
#endif

            SkAutoTUnref<SkCanvas> canvas;
            SkAutoTUnref<SkPicture> recordFrom;
            SkPictureRecorder recorderTo;
            const SkIPoint dim = bench->getSize();

            SkAutoTUnref<SkSurface> surface;
            if (Benchmark::kNonRendering_Backend != config.backend) {
                surface.reset(make_surface(config.fColorType,
                                           dim,
                                           config.backend,
                                           config.sampleCount,
                                           context));
                if (!surface.get()) {
                    logger.logError(SkStringPrintf(
                        "Device creation failure for config %s. Will skip.\n", config.name));
                    continue;
                }

                switch(benchMode) {
                    case kDeferredSilent_BenchMode:
                    case kDeferred_BenchMode:
                        canvas.reset(SkDeferredCanvas::Create(surface.get()));
                        break;
                    case kRecord_BenchMode:
                        canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY)));
                        break;
                    case kPictureRecord_BenchMode: {
                        SkPictureRecorder recorderFrom;
                        bench->draw(1, recorderFrom.beginRecording(dim.fX, dim.fY));
                        recordFrom.reset(recorderFrom.endRecording());
                        canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY)));
                        break;
                    }
                    case kNormal_BenchMode:
                        canvas.reset(SkRef(surface->getCanvas()));
                        break;
                    default:
                        SkASSERT(false);
                }
            }

            if (NULL != canvas) {
                canvas->clear(SK_ColorWHITE);
                if (FLAGS_clip)   {
                    perform_clip(canvas, dim.fX, dim.fY);
                }
                if (FLAGS_scale)  {
                    perform_scale(canvas, dim.fX, dim.fY);
                }
                if (FLAGS_rotate) {
                    perform_rotate(canvas, dim.fX, dim.fY);
                }
            }

            if (!loggedBenchName) {
                loggedBenchName = true;
                writer.bench(bench->getName(), dim.fX, dim.fY);
            }

#if SK_SUPPORT_GPU
            SkGLContextHelper* contextHelper = NULL;
            if (Benchmark::kGPU_Backend == config.backend) {
                contextHelper = gContextFactory.getGLContext(config.contextType);
            }
            BenchTimer timer(contextHelper);
#else
            BenchTimer timer;
#endif

            double previous = std::numeric_limits<double>::infinity();
            bool converged = false;

            // variables used to compute loopsPerFrame
            double frameIntervalTime = 0.0f;
            int frameIntervalTotalLoops = 0;

            bool frameIntervalComputed = false;
            int loopsPerFrame = 0;
            int loopsPerIter = 0;
            if (FLAGS_verbose) { SkDebugf("%s %s: ", bench->getName(), config.name); }
            if (!FLAGS_dryRun) {
                do {
                    // Ramp up 1 -> 2 -> 4 -> 8 -> 16 -> ... -> ~1 billion.
                    loopsPerIter = (loopsPerIter == 0) ? 1 : loopsPerIter * 2;
                    if (loopsPerIter >= (1<<30) || timer.fWall > FLAGS_maxMs) {
                        // If you find it takes more than a billion loops to get up to 20ms of runtime,
                        // you've got a computer clocked at several THz or have a broken benchmark.  ;)
                        //     "1B ought to be enough for anybody."
                        logger.logError(SkStringPrintf(
                            "\nCan't get %s %s to converge in %dms (%d loops)",
                             bench->getName(), config.name, FLAGS_maxMs, loopsPerIter));
                        break;
                    }

                    if ((benchMode == kRecord_BenchMode || benchMode == kPictureRecord_BenchMode)) {
                        // Clear the recorded commands so that they do not accumulate.
                        canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY)));
                    }

                    timer.start();
                    // Inner loop that allows us to break the run into smaller
                    // chunks (e.g. frames). This is especially useful for the GPU
                    // as we can flush and/or swap buffers to keep the GPU from
                    // queuing up too much work.
                    for (int loopCount = loopsPerIter; loopCount > 0; ) {
                        // Save and restore around each call to draw() to guarantee a pristine canvas.
                        SkAutoCanvasRestore saveRestore(canvas, true/*also save*/);

                        int loops;
                        if (frameIntervalComputed && loopCount > loopsPerFrame) {
                            loops = loopsPerFrame;
                            loopCount -= loopsPerFrame;
                        } else {
                            loops = loopCount;
                            loopCount = 0;
                        }

                        if (benchMode == kPictureRecord_BenchMode) {
                            recordFrom->draw(canvas);
                        } else {
                            bench->draw(loops, canvas);
                        }

                        if (kDeferredSilent_BenchMode == benchMode) {
                            static_cast<SkDeferredCanvas*>(canvas.get())->silentFlush();
                        } else if (NULL != canvas) {
                            canvas->flush();
                        }

    #if SK_SUPPORT_GPU
                        // swap drawing buffers on each frame to prevent the GPU
                        // from queuing up too much work
                        if (NULL != glContext) {
                            glContext->swapBuffers();
                        }
    #endif
                    }



                    // Stop truncated timers before GL calls complete, and stop the full timers after.
                    timer.truncatedEnd();
    #if SK_SUPPORT_GPU
                    if (NULL != glContext) {
                        context->flush();
                        SK_GL(*glContext, Finish());
                    }
    #endif
                    timer.end();

                    // setup the frame interval for subsequent iterations
                    if (!frameIntervalComputed) {
                        frameIntervalTime += timer.fWall;
                        frameIntervalTotalLoops += loopsPerIter;
                        if (frameIntervalTime >= FLAGS_minMs) {
                            frameIntervalComputed = true;
                            loopsPerFrame =
                              (int)(((double)frameIntervalTotalLoops / frameIntervalTime) * FLAGS_minMs);
                            if (loopsPerFrame < 1) {
                                loopsPerFrame = 1;
                            }
    //                        SkDebugf("  %s has %d loops in %f ms (normalized to %d)\n",
    //                                 bench->getName(), frameIntervalTotalLoops,
    //                                 timer.fWall, loopsPerFrame);
                        }
                    }

                    const double current = timer.fWall / loopsPerIter;
                    if (FLAGS_verbose && current > previous) { SkDebugf("↑"); }
                    if (FLAGS_verbose) { SkDebugf("%.3g ", current); }
                    converged = HasConverged(previous, current, timer.fWall);
                    previous = current;
                } while (!FLAGS_runOnce && !converged);
            }
            if (FLAGS_verbose) { SkDebugf("\n"); }

            if (!FLAGS_dryRun && FLAGS_outDir.count() && Benchmark::kNonRendering_Backend != config.backend) {
                SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
                if (image.get()) {
                    saveFile(bench->getName(), config.name, FLAGS_outDir[0],
                             image);
                }
            }

            if (FLAGS_runOnce) {
                // Let's not mislead ourselves by looking at Debug build or single iteration bench times!
                continue;
            }

            // Normalize to ms per 1000 iterations.
            const double normalize = 1000.0 / loopsPerIter;
            const struct { char shortName; const char* longName; double ms; } times[] = {
                {'w', "msecs",  normalize * timer.fWall},
                {'W', "Wmsecs", normalize * timer.fTruncatedWall},
                {'c', "cmsecs", normalize * timer.fCpu},
                {'C', "Cmsecs", normalize * timer.fTruncatedCpu},
                {'g', "gmsecs", normalize * timer.fGpu},
            };

            writer.config(config.name);
            for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) {
                if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms > 0) {
                    writer.timer(times[i].longName, times[i].ms);
                }
            }
        }
    }
#if SK_SUPPORT_GPU
    gContextFactory.destroyContexts();
#endif
    return 0;
}
void CopyPropagationPass2::CollectVariables()
{
  assert(procDef != NULL) ;
  if (killMap.empty() == false)
  {
    ClearMap() ;
  }
  assert(killMap.empty() == true) ;
  assert(procDef != NULL) ;
  SymbolTable* symTab = procDef->get_symbol_table() ;
  Iter<SymbolTableObject*> symIter = 
    symTab->get_symbol_table_object_iterator() ;
  while (symIter.is_valid())
  {
    if (is_a<VariableSymbol>(symIter.current()))
    {
      // For each variable symbol, create a new list of statement/int pairs
      //  and add that to the kill map
      list<std::pair<Statement*, int> >* assocList = 
	new list<std::pair<Statement*, int> > ;
      killMap[to<VariableSymbol>(symIter.current())] = assocList ;
    }
    else if (is_a<ParameterSymbol>(symIter.current()))
    {
      // If we are compiling a module, we also have to find the argument
      //  (which should be a struct) and collect all of those variable
      //  symbols..
      ParameterSymbol* nextParm =
	dynamic_cast<ParameterSymbol*>(symIter.current()) ;
      assert(nextParm != NULL) ;

      // Now check that we have a struct type
      DataType* parmType = nextParm->get_type()->get_base_type() ;
      StructType* parmStructType =
        dynamic_cast<StructType*>(parmType) ;

      if (parmStructType == NULL)
      {
	list<std::pair<Statement*, int> >* assocList =
	  new list<std::pair<Statement*, int> > ;
	killMap[dynamic_cast<VariableSymbol*>(symIter.current())] = assocList ;
	symIter.next() ;
	continue ;
      }

      // Go through this symbol table, just like the parent table...
      SymbolTable* structSymTab = parmStructType->get_group_symbol_table() ;

      Iter<SymbolTableObject*> structSymIter =
        structSymTab->get_symbol_table_object_iterator() ;

      while (structSymIter.is_valid())
      {
	// These should all be variable symbols!
	if (is_a<FieldSymbol>(structSymIter.current()))
	{
	  // For each variable symbol, create a new list of statement/int pairs
	  //  and add that to the killMap.
	  list<std::pair<Statement*, int> >* assocList =
	    new list<std::pair<Statement*, int> > ;
	  
	  killMap[to<VariableSymbol>(structSymIter.current())] = assocList ;
	}
	else
	{
	  std::cerr << "Non variable symbol inside a struct!" << std::endl ;
	  assert(0) ;
	}
	
	structSymIter.next() ;
      }
    }
    symIter.next() ;
  }
}
void One2MultiArrayExpressionPass::do_procedure_definition(ProcedureDefinition* proc_def)
{
    bool kill_all = !(_preserve_one_dim->is_set());
    // access all array type declarations and create corresponding multi array types
    SuifEnv* suif_env = proc_def->get_suif_env();
    TypeBuilder* tb = (TypeBuilder*)suif_env->
        get_object_factory(TypeBuilder::get_class_name());
    (void) tb; // avoid warning
#ifdef CONVERT_TYPES
    for (Iter<ArrayType> at_iter = object_iterator<ArrayType>(proc_def);
        at_iter.is_valid();at_iter.next())
    {
        MultiDimArrayType* multi_type = 
            converter->array_type2multi_array_type(&at_iter.current());
	}
#endif //CONVERT_TYPES

    // collect tops of array access chains into this list
    list<ArrayReferenceExpression*> ref_exprs;
    for (Iter<ArrayReferenceExpression> are_iter =
		object_iterator<ArrayReferenceExpression>(proc_def);
         are_iter.is_valid(); are_iter.next())
    {
        // itself an array and parent is *not* an array
        ArrayReferenceExpression* are = &are_iter.current();
        if((kill_all || is_kind_of<ArrayReferenceExpression>(are->get_base_array_address())) &&
           !is_kind_of<ArrayReferenceExpression>(are->get_parent()))
        {
            //printf("%p \t", are);are->print_to_default();
            ref_exprs.push_back(are);
	    }
    }

    // for top all expressions, convert them to multi-exprs
    for(list<ArrayReferenceExpression*>::iterator ref_iter = ref_exprs.begin();
        ref_iter != ref_exprs.end(); ref_iter++)
    {
        ArrayReferenceExpression* top_array = *ref_iter;
        converter->convert_array_expr2multi_array_expr(top_array);
    }
#ifdef CONVERT_TYPES    
    // replace the types of all array variables
    for (Iter<VariableSymbol> iter = object_iterator<VariableSymbol>(proc_def);
            iter.is_valid();iter.next())
    {
        VariableSymbol* vd = &iter.current();
        DataType *vtype = tb->unqualify_data_type(vd->get_type());
        if (is_kind_of<ArrayType>(vtype)) {
            MultiDimArrayType* multi_type =
                    converter->array_type2multi_array_type(to<ArrayType>(vtype));
            vd->replace(vd->get_type(), tb->get_qualified_type(multi_type));
        }
    }

    // remove the remaining one-dim array types
    converter->remove_all_one_dim_array_types();
#endif //CONVERT_TYPES
    // make sure no traces of single-dim arrays are left
    if(kill_all){
        {for(Iter<ArrayReferenceExpression> iter =
            object_iterator<ArrayReferenceExpression>(proc_def);
            iter.is_valid(); iter.next())
            {
                // ArrayReferenceExpression* are = &iter.current();
                //are->print_to_default(); printf("at %p \t", are);
                suif_assert_message(false, ("ARE not eliminated"));
            }
        }
#ifdef CONVERT_TYPES
        {for(Iter<ArrayType> iter =
            object_iterator<ArrayType>(proc_def);
            iter.is_valid(); iter.next())
        {suif_assert_message(false, ("ArrayType not eliminated"));}}
#endif
    }
}
Walker::ApplyStatus mdbm_c_for_statement_walker::operator () (SuifObject *x) {
    SuifEnv *env = get_env();
    CForStatement *c_for_stmt = to<CForStatement>(x);
                
    //    if(!is_stmt_within_begin_end_hw_marks(c_for_stmt))
    //   return Walker::Continue;

    Statement *body = c_for_stmt->get_body();
             
    if (body){

        Iter<CForStatement> iter_c_for = object_iterator<CForStatement>(body);
        if(iter_c_for.is_valid())
           return Walker::Continue;
             
	StatementList *stmt_list_body = NULL;

	if(is_a<StatementList>(body))
           stmt_list_body = to<StatementList>(body); 
	else{
           stmt_list_body = create_statement_list(env);
	   c_for_stmt->set_body(0);
	   stmt_list_body->append_statement(body);
	   c_for_stmt->set_body(stmt_list_body);
        }

        Iter<Statement*> iter = stmt_list_body->get_statement_iterator();
        for( ; iter.is_valid(); iter.next()){
            Statement *child_stmt = iter.current();
            if(is_a<StoreVariableStatement>(child_stmt)){
               Iter<LoadExpression> iter2 = object_iterator<LoadExpression>(child_stmt);
               if(!iter2.is_valid())
                  break;
            }else break;
        }

        MarkStatement *end_of_mem_reads_mark = create_mark_statement(env);
	if(iter.is_valid())
           insert_statement_before(iter.current(), end_of_mem_reads_mark);
        else
           stmt_list_body->insert_statement(0, end_of_mem_reads_mark);
        BrickAnnote *ba = create_brick_annote(env, "end_of_mem_reads");
        ba->append_brick(create_suif_object_brick(env, end_of_mem_reads_mark));
        c_for_stmt->append_annote(ba);
  
        for( ; iter.is_valid(); iter.next()){
            Statement *child_stmt = iter.current();
            if(is_a<StoreStatement>(child_stmt))
               break;
        }

        MarkStatement *beg_of_mem_writes_mark = create_mark_statement(env);
	if(iter.is_valid())
           insert_statement_before(iter.current(), beg_of_mem_writes_mark);
        else
           stmt_list_body->append_statement(beg_of_mem_writes_mark);
        ba = create_brick_annote(env, "beg_of_mem_writes");
        ba->append_brick(create_suif_object_brick(env, beg_of_mem_writes_mark));
        c_for_stmt->append_annote(ba);
    }        
    
    return Walker::Continue;
}               
void EliminateArrayConvertsPass::do_procedure_definition(ProcedureDefinition* proc_def){
    suif_hash_map<ParameterSymbol*, Type*> params;
    TypeBuilder *tb = (TypeBuilder*)
         get_suif_env()->get_object_factory(TypeBuilder::get_class_name());

    // collect all procedure parameters of pointer type into params list
    for(Iter<ParameterSymbol*> iter = proc_def->get_formal_parameter_iterator();
        iter.is_valid(); iter.next())
    {
        ParameterSymbol* par_sym = iter.current();
        Type* par_type = tb->unqualify_type(par_sym->get_type());

        if(is_kind_of<PointerType>(par_type)){
            // put NULLs into the map at first,
            // they will later be overwritten
            params[par_sym] = NULL;
        }
    }
    if(params.size()==0) return;    // nothing to do
    
    // walk thru all AREs and look for arrays that are in the param list
    {for(Iter<ArrayReferenceExpression> iter =
        object_iterator<ArrayReferenceExpression>(proc_def);
            iter.is_valid(); iter.next())
        {
            ArrayReferenceExpression* are = &iter.current();
            if(is_kind_of<UnaryExpression>(are->get_base_array_address())){
                UnaryExpression* ue = to<UnaryExpression>(are->get_base_array_address());
                if(ue->get_opcode() == k_convert){
                    if(is_kind_of<LoadVariableExpression>(ue->get_source())){
                        LoadVariableExpression* lve = 
                            to<LoadVariableExpression>(ue->get_source());
                        VariableSymbol* array = lve->get_source();
            
                        for(suif_hash_map<ParameterSymbol*, Type*>::iterator iter = params.begin();
                            iter!=params.end();iter++)
                        {
                            ParameterSymbol* par_sym = (*iter).first;
                            if(par_sym == array){
                                // match!
                                Type* array_type;
                                suif_hash_map<ParameterSymbol*, Type*>::iterator iter =
                                    params.find(par_sym);
                                
                                if(iter==params.end() || (*iter).second==NULL){
                                    //array_type = to<PointerType>(ue->get_result_type())->get_reference_type();
                                    array_type = tb->get_qualified_type(ue->get_result_type());
                                    params[par_sym] = array_type;
                                    //printf("%s has type ",par_sym->get_name().c_str());
                                    //array_type->print_to_default();
                                }else{
                                    array_type = params[par_sym].second;
                                    suif_assert(is_kind_of<QualifiedType>(array_type));
                                }

                                array->replace(array->get_type(), array_type);
                                remove_suif_object(ue);
                                remove_suif_object(lve);
                                lve->replace(lve->get_result_type(), tb->unqualify_type(array_type));
                                // put the LoadVar directly under ARE
                                are->set_base_array_address(lve);
                                //are->print_to_default();
                            }
                        }
                    } else {
                        suif_warning(ue->get_source(),
                            ("Expecting a LoadVariableExpression here"));
                    }
                } else {
                    suif_warning(ue, ("Disallow converts in AREs for "
                            "things other than procedure parameters"));
                }
            }
        }
    }
}
Exemple #15
0
/*
 * layout_frame -- Assign stack frame locations to each variable that needs one.
 * Store the offsets in frame_map.
 *
 * A local variable needs a memory-stack location unless it is never used or it
 * is a memory-passed parameter.
 */
void
CodeFinIa64::layout_frame()
{
    debug(4, "... determine offsets from $sp for variables");

    // Force max_arg_area to be a 16-byte multiple to be sure that the local-
    // storage area starts on a 16-byte boundary.

    max_arg_area = (max_arg_area + 15) & -16;

    // Unless this is a leaf procedure, reserve a 16-byte scratch area for
    // callees at the young end of the current frame.

    int scratch_area_size = is_leaf ? 0 : 16;

    // Frame_offset is the running offset of the current variable in the
    // local-storage area.  Initialize it to the distance between the young
    // end of the frame and the local-storage area.

    frame_offset = scratch_area_size + max_arg_area;

    SymTable *st = cur_unit->get_symbol_table();
    Iter<SymbolTableObject*> iter = st->get_symbol_table_object_iterator();
    for ( ; iter.is_valid(); iter.next()) {
	SymbolTableObject *sto = iter.current();

	if (is_kind_of<VarSym>(sto)) {
	    VarSym *v = (VarSym*)sto;

	    if (!is_reg_param(v) && is_a<ParameterSymbol>(v))
		continue;				// v's in caller's frame

	    Map<Sym*,int>::iterator v_handle = frame_map.find(v);
	    if (v_handle == frame_map.end())
		continue;				// v never used

	    // Here v is an automatic variable, other than a stack-passed
	    // parameter, that is actually used in the program.  First,
	    // adjust frame_offset to accommodate v'a alignment.  The
	    // frame_offset is already a multiple of four bytes.  An
	    // alignment value greater than four bytes will itself be a
	    // multiple of four.  Round frame_offset up if necessary to
	    // satisfy that alignment constraint.

	    TypeId v_type = get_type(v);
	    int v_align = get_bit_alignment(v_type) >> 3; // in bytes
	    if (v_align > 4) {
		claim(v_align % 4 == 0);
		frame_offset =
		    ((frame_offset + v_align - 1) / v_align) * v_align;
	    }
	    (*v_handle).second = frame_offset;		// update frame_map

	    // Now allocate a multiple of four bytes to v.

	    int v_size = get_bit_size(v_type) >> 3;	// v's size in bytes
	    frame_offset += (v_size + 3) & -4;
	}
    }

    // Compute number of bytes for registers saved in memory between locals
    // and the frame base.
    
    save_area_size = saved_reg_set[CLASS_GR].size() * 8 +
		     saved_reg_set[CLASS_BR].size() * 8 +
		     saved_reg_set[CLASS_FR].size() * 16;

    // The sum of local-area and save-area sizes must be a multiple of 16.
    // Frame_offset is now the local-area size.  Pad it to make the sum a
    // 16-byte multiple.  (Hint: save_area_size is already a multiple of 8.)

    claim((frame_offset & 3) == 0);			// now a 4-byte multiple
    frame_offset = (frame_offset + (save_area_size & 15) + 15) & -16;

    debug(4, "... determine offsets from $sp for memory-passed parameters");

    // Process parameter list in order.  Set running offset param_offset for
    // memory-passed parameters.  Also determine the highest GR arg register
    // used.
    // FIXME: does not allow for aggregates passed partly in regs and partly
    // in memory.

    int param_offset = frame_offset + save_area_size;
    if (param_offset < (scratch_area_size + 16))
	param_offset = (scratch_area_size + 16);

    for (int i = 0; i < get_formal_param_count(cur_unit); i++) {
	VarSym *p = get_formal_param(cur_unit, i);

	// Each parameter consumes a multiple of 8 bytes.

	int p_size = get_bit_size(get_type(p)) >> 3;	// in bytes
	p_size = (p_size + 7) & -8;

	if (is_reg_param(p)) {
	    int first_reg = get_param_reg(p);

	    if (GR_ARG0 <= first_reg && first_reg <= GR_LAST_ARG) {
		claim(first_reg > max_in_reg);

		max_in_reg = first_reg + (p_size / 8) - 1;
		if (max_in_reg > GR_LAST_ARG)
		    max_in_reg = GR_LAST_ARG;
	    }
	} else {
	    claim(frame_map.count(p) == 0);

	    frame_map[p] = param_offset;
	    param_offset += p_size;
	}
    }

    // In a varargs procedure, the GR parameter registers that are not used
    // by named arguments must be spilled to memory adjacent to any
    // parameters passed in memory by the caller.  So in the varargs case,
    // the first thing at the old end of the frame (beginning actually in
    // the caller's scratch area) is a varargs spill area.  Note that we
    // increase max_in_reg to cover any reg-passed, unnamed varargs.

    if (is_varargs) {
	va_area_size = 64 - 8 * (max_in_reg - GR_STACK0 + 1);
	max_in_reg = GR_LAST_ARG;
    } else {
	va_area_size = 0;
    }

    // Frame size is the sum of the sizes of the scratch area, the
    // outgoing-arg area, the local-storage area, the callee-saves-register
    // area, and the register-passed-varargs area.  (The first three have
    // already been combined in frame_offset.)  The sum of frame_offset and
    // save_area_size is already a 16-byte multiple, but va_area_size may
    // not be, so pad to bring frame_size to a multiple of 16 bytes.

    frame_size = frame_offset + save_area_size + ((va_area_size + 15) & -16);

    // For a procedure that invokes va_start, bind the variable whose symbol
    // is stored in va_first_var to the offset from SP of the first unnamed
    // argument, whether passed in memory (va_area_size == 0) or in a register
    // that has been dumped to memory (va_area_size > 0).

    claim((va_first_var == NULL) == (is_varargs == false));
    if (is_varargs)
	frame_map[va_first_var] = 
	    (va_area_size == 0) ? param_offset
				: (frame_size - (va_area_size - 16));
}
static void dismantle_multi_dim_array_expression(
		SuifEnv *env,
		MultiDimArrayExpression *exp,
		TypeBuilder *type_builder,
		suif_hash_map<MultiDimArrayType *,Type *> &type_map) 
{
    Expression *ref_exp = exp->get_array_address();

    Type *typ = ref_exp->get_result_type();
    if (is_kind_of<PointerType>(typ))
	typ = to<PointerType>(typ)->get_reference_type();
    if (is_kind_of<ReferenceType>(typ))
        typ = to<ReferenceType>(typ)->get_reference_type();

    if (is_kind_of<QualifiedType>(typ))
        typ = to<QualifiedType>(typ)->get_base_type();

    simple_stack<Expression *> lows;
    int dims;
    Type *rep_type;

    if (is_kind_of<MultiDimArrayType>(typ)) {
    	MultiDimArrayType *mdatyp= to<MultiDimArrayType>(typ);
	suif_hash_map<MultiDimArrayType *,Type *>::iterator iter =
		type_map.find(mdatyp);
	kernel_assert_message(iter != type_map.end(),
		("Error - type not converted"));
	rep_type = (*iter).second;
    	dims = exp->get_index_count();
    	for (int i = dims - 1;i >=0 ; i--) {
	    lows.push(mdatyp->get_lower_bound(i));
	    }
	}
    else {
	// this arm should never be taken, so assert
	kernel_assert_message(false,("This code should not have been accessed"));
	rep_type = typ;
        dims = 0;
	while (is_kind_of<ArrayType>(typ)) {
	    ArrayType *atype = to<ArrayType>(typ);
	    dims ++;
	    lows.push(atype->get_lower_bound());
	    typ = to<QualifiedType>(atype->get_element_type())->get_base_type();
	    }
	}

    exp->replace(ref_exp,0);
    ref_exp->set_parent(0);
    int index_count = exp->get_index_count();
    for (int i = 0;i < index_count;i ++) {
	Type *ref_type = rep_type;
	for (int j = 0;j <= i;j ++) {
	    ref_type = type_builder->unqualify_type(ref_type);
	    ref_type = to<ArrayType>(ref_type)->get_element_type();
	    }
	ref_type = type_builder->unqualify_type(ref_type);
	ref_type = type_builder->get_pointer_type(ref_type);
	Expression *index = exp->get_index(index_count - i - 1);



	// process nested multi dim arra expressions
        for (Iter<MultiDimArrayExpression> iter =
                object_iterator<MultiDimArrayExpression>(index);
         iter.is_valid();
         iter.next()) {
        MultiDimArrayExpression *mexpr = &iter.current();
        dismantle_multi_dim_array_expression(env,mexpr,type_builder,type_map);
        }
	
	exp->replace(index,0);
	index->set_parent(0);
        ref_exp = create_array_reference_expression(
		env,to<DataType>(ref_type),ref_exp,
		index);
	}
    exp->get_parent()->replace(exp,ref_exp);
}
Exemple #17
0
  void
audit_opnds(FILE *fp, const char *heading)
{
  int size_reg = 0;
  int size_var = 0;
  int size_immed_integer = 0;
  int size_immed_string = 0;
  int size_addr_sym = 0;
  int size_addr_exp = 0;

  for (Iter<SymbolTableObject*> i =
      the_local_scope->get_symbol_table_object_iterator();
      i.is_valid(); i.next())
  {
    SymbolTableObject *sto = i.current();
    if (is_kind_of<IrOpnd>(sto))
      switch (static_cast<IrOpnd*>(sto)->get_kind())
      {
        case opnd::NONE:
          claim(false, "Unexpected operand kind: opnd::NONE");
        case opnd::REG_HARD:
        case opnd::REG_VIRTUAL:
          size_reg += sizeof(OpndReg);
          break;
        case opnd::VAR:
          size_var += sizeof(OpndVar);
          break;
        case opnd::IMMED_INTEGER:
          size_immed_integer += sizeof(OpndImmedInteger);
          break;
        case opnd::IMMED_STRING:
          size_immed_string += sizeof(OpndImmedString);
          break;
        case opnd::ADDR_SYM:
          size_addr_sym += sizeof(OpndAddrSym);
          break;
        case opnd::SYM_DISP:
        case opnd::INDEX_SYM_DISP:
        case opnd::BASE_DISP:
        case opnd::BASE_INDEX:
        case opnd::BASE_INDEX_DISP:
        case opnd::INDEX_SCALE_DISP:
        case opnd::BASE_INDEX_SCALE_DISP:
          size_addr_sym +=
            sizeof(OpndAddrExp) +
            sizeof(IrOpnd*) *
            static_cast<OpndAddrExp*>(sto)->get_src_count();
          break;
        default:
          claim(false, "Unknown operand kind");
      }
  }
  fprintf(fp, "%s operand storage (bytes):\n", heading);
  fprintf(fp, "  Register:          %8d\n", size_reg);
  fprintf(fp, "  Variable symbol:   %8d\n", size_var);
  fprintf(fp, "  String immediate:  %8d\n", size_immed_string);
  fprintf(fp, "  Integer immediate: %8d\n", size_immed_integer);
  fprintf(fp, "  Address symbol:    %8d\n", size_addr_sym);
  fprintf(fp, "  Address expression:%8d\n", size_addr_exp);
  fprintf(fp, "                     %8d (total)\n",
      size_reg + size_var + size_immed_string + size_immed_integer +
      size_addr_sym + size_addr_exp);
}
static void TestTLList(skiatest::Reporter* reporter) {
    typedef SkTLList<ListElement> ElList;
    typedef ElList::Iter Iter;
    SkRandom random;

    for (int i = 1; i <= 16; i *= 2) {

        ElList list1(i);
        ElList list2(i);
        Iter iter1;
        Iter iter2;
        Iter iter3;
        Iter iter4;

#if SK_ENABLE_INST_COUNT
        SkASSERT(0 == ListElement::InstanceCount());
#endif

        REPORTER_ASSERT(reporter, list1.isEmpty());
        REPORTER_ASSERT(reporter, NULL == iter1.init(list1, Iter::kHead_IterStart));
        REPORTER_ASSERT(reporter, NULL == iter1.init(list1, Iter::kTail_IterStart));
        // Try popping an empty list
        list1.popHead();
        list1.popTail();
        REPORTER_ASSERT(reporter, list1.isEmpty());
        REPORTER_ASSERT(reporter, list1 == list2);

        // Create two identical lists, one by appending to head and the other to the tail.
        list1.addToHead(ListElement(1));
        list2.addToTail(ListElement(1));
#if SK_ENABLE_INST_COUNT
        SkASSERT(2 == ListElement::InstanceCount());
#endif
        iter1.init(list1, Iter::kHead_IterStart);
        iter2.init(list1, Iter::kTail_IterStart);
        REPORTER_ASSERT(reporter, iter1.get()->fID == iter2.get()->fID);
        iter3.init(list2, Iter::kHead_IterStart);
        iter4.init(list2, Iter::kTail_IterStart);
        REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, list1 == list2);

        list2.reset();

        // use both before/after in-place construction on an empty list
        SkNEW_INSERT_IN_LLIST_BEFORE(&list2, list2.headIter(), ListElement, (1));
        REPORTER_ASSERT(reporter, list2 == list1);
        list2.reset();

        SkNEW_INSERT_IN_LLIST_AFTER(&list2, list2.tailIter(), ListElement, (1));
        REPORTER_ASSERT(reporter, list2 == list1);

        // add an element to the second list, check that iters are still valid
        iter3.init(list2, Iter::kHead_IterStart);
        iter4.init(list2, Iter::kTail_IterStart);
        list2.addToHead(ListElement(2));

#if SK_ENABLE_INST_COUNT
        SkASSERT(3 == ListElement::InstanceCount());
#endif

        REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, 1 == Iter(list2, Iter::kTail_IterStart).get()->fID);
        REPORTER_ASSERT(reporter, 2 == Iter(list2, Iter::kHead_IterStart).get()->fID);
        REPORTER_ASSERT(reporter, list1 != list2);
        list1.addToHead(ListElement(2));
        REPORTER_ASSERT(reporter, list1 == list2);
#if SK_ENABLE_INST_COUNT
        SkASSERT(4 == ListElement::InstanceCount());
#endif
        REPORTER_ASSERT(reporter, !list1.isEmpty());

        list1.reset();
        list2.reset();
#if SK_ENABLE_INST_COUNT
        SkASSERT(0 == ListElement::InstanceCount());
#endif
        REPORTER_ASSERT(reporter, list1.isEmpty() && list2.isEmpty());

        // randomly perform insertions and deletions on a list and perform tests
        int count = 0;
        for (int j = 0; j < 100; ++j) {
            if (list1.isEmpty() || random.nextBiasedBool(3  * SK_Scalar1 / 4)) {
                int id = j;
                // Choose one of three ways to insert a new element: at the head, at the tail,
                // before a random element, after a random element
                int numValidMethods = 0 == count ? 2 : 4;
                int insertionMethod = random.nextULessThan(numValidMethods);
                switch (insertionMethod) {
                    case 0:
                        list1.addToHead(ListElement(id));
                        break;
                    case 1:
                        list1.addToTail(ListElement(id));
                        break;
                    case 2: // fallthru to share code that picks random element.
                    case 3: {
                        int n = random.nextULessThan(list1.count());
                        Iter iter = list1.headIter();
                        // remember the elements before/after the insertion point.
                        while (n--) {
                            iter.next();
                        }
                        Iter prev(iter);
                        Iter next(iter);
                        next.next();
                        prev.prev();

                        SkASSERT(NULL != iter.get());
                        // insert either before or after the iterator, then check that the
                        // surrounding sequence is correct.
                        if (2 == insertionMethod) {
                            SkNEW_INSERT_IN_LLIST_BEFORE(&list1, iter, ListElement, (id));
                            Iter newItem(iter);
                            newItem.prev();
                            REPORTER_ASSERT(reporter, newItem.get()->fID == id);

                            if (NULL != next.get()) {
                                REPORTER_ASSERT(reporter, next.prev()->fID == iter.get()->fID);
                            }
                            if (NULL != prev.get()) {
                                REPORTER_ASSERT(reporter, prev.next()->fID == id);
                            }
                        } else {
                            SkNEW_INSERT_IN_LLIST_AFTER(&list1, iter, ListElement, (id));
                            Iter newItem(iter);
                            newItem.next();
                            REPORTER_ASSERT(reporter, newItem.get()->fID == id);

                            if (NULL != next.get()) {
                                REPORTER_ASSERT(reporter, next.prev()->fID == id);
                            }
                            if (NULL != prev.get()) {
                                REPORTER_ASSERT(reporter, prev.next()->fID == iter.get()->fID);
                            }
                        }
                    }
                }
                ++count;
            } else {
                // walk to a random place either forward or backwards and remove.
                int n = random.nextULessThan(list1.count());
                Iter::IterStart start;
                ListElement* (Iter::*incrFunc)();

                if (random.nextBool()) {
                    start = Iter::kHead_IterStart;
                    incrFunc = &Iter::next;
                } else {
                    start = Iter::kTail_IterStart;
                    incrFunc = &Iter::prev;
                }

                // find the element
                Iter iter(list1, start);
                while (n--) {
                    REPORTER_ASSERT(reporter, NULL != iter.get());
                    (iter.*incrFunc)();
                }
                REPORTER_ASSERT(reporter, NULL != iter.get());

                // remember the prev and next elements from the element to be removed
                Iter prev = iter;
                Iter next = iter;
                prev.prev();
                next.next();
                list1.remove(iter.get());

                // make sure the remembered next/prev iters still work
                Iter pn = prev; pn.next();
                Iter np = next; np.prev();
                // pn should match next unless the target node was the head, in which case prev
                // walked off the list.
                REPORTER_ASSERT(reporter, pn.get() == next.get() || NULL == prev.get());
                // Similarly, np should match prev unless next originally walked off the tail.
                REPORTER_ASSERT(reporter, np.get() == prev.get() || NULL == next.get());
                --count;
            }
            REPORTER_ASSERT(reporter, count == list1.count());
#if SK_ENABLE_INST_COUNT
            SkASSERT(count == ListElement::InstanceCount());
#endif
        }
        list1.reset();
#if SK_ENABLE_INST_COUNT
        SkASSERT(0 == ListElement::InstanceCount());
#endif
    }
}
Statement* scope_statement_walker::dismantle_scope_statement(ScopeStatement *the_scope_stat){
    ProcedureDefinition* proc_def = get_procedure_definition(the_scope_stat);
    Statement *body = the_scope_stat->get_body();
    if(body==NULL){
        the_scope_stat->print_to_default();
    }
    body->set_parent(0);
    the_scope_stat->set_body(0);

    // This is a bug?
    //    remove_suif_object(body);

    SymbolTable * symbol_table = the_scope_stat->get_symbol_table();
    DefinitionBlock * definition_block = the_scope_stat->get_definition_block();

    SymbolTable *new_symbol_table = proc_def->get_symbol_table();
    DefinitionBlock *new_definition_block = proc_def->get_definition_block();

    if (symbol_table != 0) {

	// start by creating a name for the symbol in the new symbol table
    Iter<SymbolTable::lookup_table_pair> piter = symbol_table->get_lookup_table_iterator();
	while (piter.is_valid()) {
	    indexed_list<LString,SymbolTableObject*>::pair p = piter.current();
	    SymbolTableObject * obj = p.second;
	    const LString &name = p.first;
	    new_symbol_table->add_lookup_table(name,obj);
	    piter.next();
    }

    // now move all symbols into the symbol table for the procedure scope
	// at the same time, we delete them from the current symbol table and
	// remove all references to this symbol table from the name list attached
	// to the symbol
	// DLH 
	//    I modifed this to build a list so we aren't iterating over
	// a changing object (which didn't work. and I don't expect it to)

	list<SymbolTableObject*> l;
    {for (Iter<SymbolTableObject*> iter = 
	       symbol_table->get_symbol_table_object_iterator();
	     iter.is_valid(); iter.next()) {
	    l.push_back(iter.current());
    }}

	for (list<SymbolTableObject*>::iterator iter =
	       l.begin(); iter != l.end(); iter++) 
    {
	    SymbolTableObject *object = *iter;
	    symbol_table->remove_symbol_table_object(object);
            rename_if_collision(object, new_symbol_table);
            new_symbol_table->add_symbol(object);
	    //	    symbol_table->remove_all_from_lookup_table(object);
	    //	    object->remove_all_from_name(symbol_table);
	    }
    }

    if (definition_block != 0) {
	// move all definition block entries
	    int i = definition_block->get_variable_definition_count();
	    while (i > 0){
	        i--;
	        VariableDefinition *next = definition_block->remove_variable_definition(i);
	        new_definition_block->append_variable_definition(next);
	    }

        i = definition_block->get_procedure_definition_count();
        while (i > 0){
            i--;
            ProcedureDefinition *next = definition_block->remove_procedure_definition(i);
            new_definition_block->append_procedure_definition(next);
        }
    }
    the_scope_stat->get_parent()->replace(the_scope_stat, body);
    return body;
}
void DismantleStructuredReturns::do_file_set_block( FileSetBlock* file_set_block ) {
    suif_map<CProcedureType *,QualifiedType *> type_map;
    list<ArrayReferenceExpression*> ref_exprs;
    SuifEnv *env = 0;
    TypeBuilder *tb = 0;
    VoidType *vt = 0;
    for (Iter<ProcedureSymbol> iter =
                object_iterator<ProcedureSymbol>(file_set_block);
	iter.is_valid();
	iter.next()) {
	ProcedureSymbol *sym = &iter.current();
	Type *type = sym->get_type();
	if (!is_kind_of<CProcedureType>(type))
	    continue;
	CProcedureType *cp_type = to<CProcedureType>(type);
	type = cp_type->get_result_type();
	if (!env) {
	    env = type->get_suif_env();
	    tb = (TypeBuilder*)
                env->get_object_factory(TypeBuilder::get_class_name());
	    vt = tb->get_void_type();
	    }
	suif_map<CProcedureType *,QualifiedType *>::iterator t_iter = type_map.find(cp_type);

	QualifiedType *qtype;
	
 	if (t_iter == type_map.end()) {
	    if (!is_kind_of<GroupType>(type) && !is_kind_of<ArrayType>(type))
                continue;
	    qtype = tb->get_qualified_type(
                        tb->get_pointer_type(to<DataType>(type)));

	    cp_type->set_result_type(vt);
	    
	    cp_type->insert_argument(0,qtype);
	    type_map.enter_value(cp_type,qtype);
	    }
	else {
	    qtype = (*t_iter).second;
	    }
	ProcedureDefinition *def = sym->get_definition();
	if (!def) 
	    continue;
	ParameterSymbol *par = create_parameter_symbol(env,qtype);
	def->get_symbol_table()->append_symbol_table_object(par);
        def->insert_formal_parameter(0,par);
	//	Convert all returns into assigned and returns
	for (Iter<ReturnStatement> ret_iter = object_iterator<ReturnStatement>(def->get_body());
        	ret_iter.is_valid();
        	ret_iter.next()) {
	    ReturnStatement *ret = &ret_iter.current();
	    Expression *retval = ret->get_return_value();
	    ret->set_return_value(0);
	    retval->set_parent(0);
	    insert_statement_before(ret,
			create_store_statement(env,retval,create_var_use(par)));
	    }
	}
    //	Change all calls to the new form
    for (Iter<CallStatement> cs_iter =
                object_iterator<CallStatement>(file_set_block);
        cs_iter.is_valid();
        cs_iter.next()) {
        CallStatement *call = &cs_iter.current();
	Type *type = call->get_callee_address()->get_result_type();
	Type *p_type = tb->unqualify_type(to<PointerType>(type)->get_reference_type());
        if (!is_kind_of<PointerType>(p_type))
            continue;
        p_type = tb->unqualify_type(to<PointerType>(p_type)->get_reference_type());

	if (!is_kind_of<CProcedureType>(p_type))
	    continue;
	CProcedureType *cp_type = to<CProcedureType>(p_type);
	
	suif_map<CProcedureType *,QualifiedType *>::iterator t_iter = type_map.find(cp_type);
	if (t_iter == type_map.end())
	    continue;
	QualifiedType *qtype = (*t_iter).second;
	DataType *var_type = to<DataType>(tb->unqualify_type(to<PointerType>(qtype->get_base_type())
		->get_reference_type()));
	VariableSymbol *var =
      	    new_anonymous_variable(env,call,tb->get_qualified_type(var_type));
	Expression *exp = create_symbol_address_expression(
		env,
		tb->get_pointer_type(var_type),
		var);
        call->insert_argument(0,exp);
        call->set_destination(0);
	}

    for (Iter<CallExpression> ce_iter =
                object_iterator<CallExpression>(file_set_block);
        ce_iter.is_valid();
        ce_iter.next()) {
        CallExpression *call = &ce_iter.current();
        Type *type = call->get_callee_address()->get_result_type();
        Type *p_type = tb->unqualify_type(to<PointerType>(type)->get_reference_type());
	if (!is_kind_of<PointerType>(p_type))
            continue;
	p_type = tb->unqualify_type(to<PointerType>(p_type)->get_reference_type());
        if (!is_kind_of<CProcedureType>(p_type))
            continue;
        CProcedureType *cp_type = to<CProcedureType>(p_type);
;
        suif_map<CProcedureType *,QualifiedType *>::iterator t_iter = type_map.find(cp_type);
        if (t_iter == type_map.end())
            continue;
        QualifiedType *qtype = (*t_iter).second;
        DataType *var_type = to<DataType>(tb->unqualify_type(to<PointerType>(qtype->get_base_type())
                ->get_reference_type()));
        VariableSymbol *var =
            new_anonymous_variable(env,call,tb->get_qualified_type(var_type));
        Expression *exp = create_symbol_address_expression(
                env,
                tb->get_pointer_type(var_type),
                var);
        call->insert_argument(0,exp);

	Statement *loc = get_expression_owner(call);
	call->get_parent()->replace(call,create_var_use(var));
	call->set_parent(0);
        suif_assert(vt != 0);
        call->set_result_type(vt);

	EvalStatement *es = create_eval_statement(env);
	insert_statement_before(loc,es);
	// Would be better to turn this into a call statement
	es->append_expression(call);
        }
    }
static void TestTInternalLList(skiatest::Reporter* reporter) {
    SkTInternalLList<ListElement> list;
    ListElement elements[4] = {
        ListElement(0),
        ListElement(1),
        ListElement(2),
        ListElement(3),
    };

    // list should be empty to start with
    check_list(list, reporter, true, 0, false, false, false, false, elements);

    list.addToHead(&elements[0]);

    check_list(list, reporter, false, 1, true, false, false, false, elements);

    list.addToHead(&elements[1]);
    list.addToHead(&elements[2]);
    list.addToHead(&elements[3]);

    check_list(list, reporter, false, 4, true, true, true, true, elements);

    // test out iterators
    typedef SkTInternalLList<ListElement>::Iter Iter;
    Iter iter;

    ListElement* cur = iter.init(list, Iter::kHead_IterStart);
    for (int i = 0; NULL != cur; ++i, cur = iter.next()) {
        REPORTER_ASSERT(reporter, cur->fID == 3-i);
    }

    cur = iter.init(list, Iter::kTail_IterStart);
    for (int i = 0; NULL != cur; ++i, cur = iter.prev()) {
        REPORTER_ASSERT(reporter, cur->fID == i);
    }

    // remove middle, frontmost then backmost
    list.remove(&elements[1]);
    list.remove(&elements[3]);
    list.remove(&elements[0]);

    check_list(list, reporter, false, 1, false, false, true, false, elements);

    // remove last element
    list.remove(&elements[2]);

    // list should be empty again
    check_list(list, reporter, true, 0, false, false, false, false, elements);

    // test out methods that add to the middle of the list.
    list.addAfter(&elements[1], NULL);
    check_list(list, reporter, false, 1, false, true, false, false, elements);

    list.remove(&elements[1]);

    list.addBefore(&elements[1], NULL);
    check_list(list, reporter, false, 1, false, true, false, false, elements);

    list.addBefore(&elements[0], &elements[1]);
    check_list(list, reporter, false, 2, true, true, false, false, elements);

    list.addAfter(&elements[3], &elements[1]);
    check_list(list, reporter, false, 3, true, true, false, true, elements);

    list.addBefore(&elements[2], &elements[3]);
    check_list(list, reporter, false, 4, true, true, true, true, elements);

    cur = iter.init(list, Iter::kHead_IterStart);
    for (int i = 0; NULL != cur; ++i, cur = iter.next()) {
        REPORTER_ASSERT(reporter, cur->fID == i);
    }
}
int main (int argc, char * const argv[]) {
    SkAutoGraphics ag;
    
    const char* writePath = NULL;   // if non-null, where we write the originals
    const char* readPath = NULL;    // if non-null, were we read from to compare

    char* const* stop = argv + argc;
    for (++argv; argv < stop; ++argv) {
        if (strcmp(*argv, "-w") == 0) {
            argv++;
            if (argv < stop && **argv) {
                writePath = *argv;
            }
        } else if (strcmp(*argv, "-r") == 0) {
            argv++;
            if (argv < stop && **argv) {
                readPath = *argv;
            }
        }
    }
    
    Iter iter;
    GM* gm;
	
    while ((gm = iter.next()) != NULL) {
		SkISize size = gm->getISize();
        SkDebugf("creating... %s [%d %d]\n", gm->shortName(),
                 size.width(), size.height());

		SkBitmap bitmap;
		for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
			bitmap.setConfig(gRec[i].fConfig, size.width(), size.height());
			bitmap.allocPixels();
			bitmap.eraseColor(0);
			SkCanvas canvas(bitmap);

			gm->draw(&canvas);
            
            SkString name = make_name(gm->shortName(), gRec[i].fName);

            if (writePath) {
                SkString path = make_filename(writePath, name);
                bool success = write_bitmap(path, bitmap);
                if (!success) {
                    fprintf(stderr, "FAILED to write %s\n", path.c_str());
                }
            } else if (readPath) {
                SkString path = make_filename(readPath, name);
                SkBitmap orig;
                bool success = SkImageDecoder::DecodeFile(path.c_str(), &orig,
                                    SkBitmap::kARGB_8888_Config,
                                    SkImageDecoder::kDecodePixels_Mode, NULL);
                if (success) {
                    compare(bitmap, orig, name);
                } else {
                    fprintf(stderr, "FAILED to read %s\n", path.c_str());
                }
            }
		}
        SkDELETE(gm);
    }
    return 0;
}
void TransformSystemsToModules::Transform()
{
  assert(procDef != NULL) ;

  // Collect all the input scalars and output scalars
  list<VariableSymbol*> ports ;
  
  SymbolTable* procSymTab = procDef->get_symbol_table() ;
  bool foundInputs = false ;
  bool foundOutputs = false ;
 
  for (int i = 0 ; i < procSymTab->get_symbol_table_object_count() ; ++i)
  {
    SymbolTableObject* nextObject = procSymTab->get_symbol_table_object(i) ;

    if (nextObject->lookup_annote_by_name("InputScalar") != NULL)
    {
      VariableSymbol* toConvert = 
	dynamic_cast<VariableSymbol*>(nextObject) ;
      assert(toConvert != NULL) ;
      LString inputName = toConvert->get_name() ;
      inputName = inputName + "_in" ;
      toConvert->set_name(inputName) ;
      ports.push_back(toConvert) ;
      foundInputs = true ;
    }
    if (nextObject->lookup_annote_by_name("OutputVariable") != NULL)
    {
      VariableSymbol* toConvert = 
	dynamic_cast<VariableSymbol*>(nextObject) ;
      assert(toConvert != NULL) ;
      LString outputName = toConvert->get_name() ;
      outputName = outputName + "_out" ;
      toConvert->set_name(outputName) ;
      ports.push_back(toConvert) ;
      foundOutputs = true ;
    }
  }
  assert(foundInputs && 
	 "Could not identify inputs.  Were they removed via optimizations?") ;
  assert(foundOutputs && 
	 "Could not identify outputs.  Were they removed via optimizations?") ;

  // Determine the bit size and add everything to a new symbol table
  int bitSize = 0 ;
  GroupSymbolTable* structTable = 
    create_group_symbol_table(theEnv,
			      procDef->get_symbol_table()) ;

  std::map<VariableSymbol*, FieldSymbol*> replacementFields ;

  bool portsRemoved = false ;
  // If this was actually a new style module, we should make sure to
  //  put these in the correct order.
  if (isModule(procDef))
  {
    // Go through the original symbol table and remove any parameter 
    //  symbols that originally existed
    SymbolTable* originalSymTab = procDef->get_symbol_table() ;
    Iter<SymbolTableObject*> originalIter = 
      originalSymTab->get_symbol_table_object_iterator() ;
    while (originalIter.is_valid())
    {
      SymbolTableObject* currentObj = originalIter.current() ;
      originalIter.next() ;
      if (dynamic_cast<ParameterSymbol*>(currentObj) != NULL)
      {
	originalSymTab->remove_symbol_table_object(currentObj) ;
      }
    }
    portsRemoved = true ;

    // Sort the variable symbols in parameter order.  This is just an 
    //  insertion sort, so it could be done faster.
    list<VariableSymbol*> sortedPorts ;
    for (int i = 0 ; i < ports.size() ; ++i)
    {
      list<VariableSymbol*>::iterator portIter = ports.begin() ;
      while (portIter != ports.end())
      {
	BrickAnnote* orderAnnote = 
	  dynamic_cast<BrickAnnote*>((*portIter)->
				     lookup_annote_by_name("ParameterOrder")) ;
	if (orderAnnote == NULL)
	{
	  ++portIter ;
	  continue ;
	}
	IntegerBrick* orderBrick = 
	  dynamic_cast<IntegerBrick*>(orderAnnote->get_brick(0)) ;
	assert(orderBrick != NULL) ;
	if (orderBrick->get_value().c_int() == i)
	{
	  sortedPorts.push_back(*portIter) ;
	  break ;
	}
	++portIter ;
      }
    }
    if (sortedPorts.size() != ports.size())
    {
      OutputWarning("Warning! Analysis detected some input scalars not in"
		    " the parameter list") ;
    }
    // Replace ports with sortedPorts
    ports = sortedPorts ;
  }

  list<VariableSymbol*>::iterator portIter = ports.begin() ;  
  while (portIter != ports.end()) 
  {
    bitSize += 
      (*portIter)->get_type()->get_base_type()->get_bit_size().c_int() ;

    LString dupeName = (*portIter)->get_name() ;

    // Create offset expression:
    IntConstant* offset = 
      create_int_constant(theEnv,
			  create_data_type(theEnv,
					   IInteger(32),
					   0),
			  IInteger(bitSize)) ;


    QualifiedType* dupeType = (*portIter)->get_type() ;
    // Deal with the case where reference types were passed in
    ReferenceType* refType = 
      dynamic_cast<ReferenceType*>(dupeType->get_base_type()) ;
    while (refType != NULL)
    {
      dupeType = dynamic_cast<QualifiedType*>(refType->get_reference_type()) ;
      assert(dupeType != NULL) ;
      refType = dynamic_cast<ReferenceType*>(dupeType->get_base_type()) ;
    }

    // Create a new variable symbol clone
    FieldSymbol* dupe = 
      create_field_symbol(theEnv,
			  dupeType,
			  offset,
			  dupeName) ;
        
    structTable->append_symbol_table_object(dupe) ;

    // Make the connection with the duplicated symbol
    replacementFields[(*portIter)] = dupe ;

    // Remove the original variable symbol from the procedure definition
    //  symbol table.
    if (!portsRemoved)
    {
      procDef->get_symbol_table()->remove_symbol_table_object(*portIter) ;
    }
    
    ++portIter ;
  }
  assert(bitSize != 0);

  StructType* moduleStruct = 
    create_struct_type(theEnv,
		       IInteger(bitSize),
		       0, // bit_alignment
		       TempName(procDef->get_procedure_symbol()->get_name()),
		       0, // is_complete
		       structTable) ;

  
  Iter<FileBlock*> fBlocks = 
    theEnv->get_file_set_block()->get_file_block_iterator() ;
  
  assert(fBlocks.is_valid()) ;
  (fBlocks.current())->get_symbol_table()->append_symbol_table_object(moduleStruct) ;
  
  // This is commented out because it is in the file state block
  //procDef->get_symbol_table()->append_symbol_table_object(moduleStruct) ;

  QualifiedType* qualifiedModuleStruct =
    create_qualified_type(theEnv,
			  moduleStruct,
			  TempName(LString("qualifiedModuleStruct"))) ;
  
  procDef->get_symbol_table()->append_symbol_table_object(qualifiedModuleStruct) ;

  // Create an instance of this type and add it to the symbol table.
  ParameterSymbol* structInstance = 
    create_parameter_symbol(theEnv,
			   qualifiedModuleStruct,
			   TempName(LString("structInstance"))) ;

  procDef->get_symbol_table()->append_symbol_table_object(structInstance) ;

  // Now, set up the procedure symbol to take the struct and return the 
  //  struct.
  assert(procDef != NULL) ;
  ProcedureSymbol* procSym = procDef->get_procedure_symbol() ;
  assert(procSym != NULL) ;
  ProcedureType* procType = procSym->get_type() ;
  assert(procType != NULL) ;
  CProcedureType* cProcType = dynamic_cast<CProcedureType*>(procType) ;
  assert(cProcType != NULL) ;

  // Instead of appending the struct argument, we need to replace all of the 
  //  arguments with the struct.

  while (cProcType->get_argument_count() > 0)
  {
    cProcType->remove_argument(0) ;
  }

  cProcType->set_result_type(moduleStruct) ;
  cProcType->append_argument(qualifiedModuleStruct) ;

  // Now go through all load variable expressions and replace them all with
  //  field symbol values if appropriate
  
  list<LoadVariableExpression*>* allLoads = 
    collect_objects<LoadVariableExpression>(procDef->get_body()) ;

  list<LoadVariableExpression*>::iterator loadIter = allLoads->begin() ;
  while (loadIter != allLoads->end())
  {
    VariableSymbol* currentVariable = (*loadIter)->get_source() ;
    if (replacementFields.find(currentVariable) != replacementFields.end())
    {
      (*loadIter)->set_source(replacementFields[currentVariable]) ;
    }
    ++loadIter ;
  }
  delete allLoads ;

  // Also replace all of the definitions with the field symbol
  list<StoreVariableStatement*>* allStoreVars = 
    collect_objects<StoreVariableStatement>(procDef->get_body()) ;
  list<StoreVariableStatement*>::iterator storeVarIter = allStoreVars->begin();
  while (storeVarIter != allStoreVars->end())
  {
    VariableSymbol* currentDest = (*storeVarIter)->get_destination() ;
    if (replacementFields.find(currentDest) != replacementFields.end())
    {
      (*storeVarIter)->set_destination(replacementFields[currentDest]) ;
    }
    ++storeVarIter ;
  }
  delete allStoreVars ;

  list<SymbolAddressExpression*>* allSymAddr = 
    collect_objects<SymbolAddressExpression>(procDef->get_body()) ;
  list<SymbolAddressExpression*>::iterator symAddrIter = allSymAddr->begin() ;
  while (symAddrIter != allSymAddr->end())
  {
    VariableSymbol* currentVar = 
      dynamic_cast<VariableSymbol*>((*symAddrIter)->get_addressed_symbol()) ;
    if (currentVar != NULL &&
	replacementFields.find(currentVar) != replacementFields.end())
    {
      (*symAddrIter)->set_addressed_symbol(replacementFields[currentVar]) ;
    }
    ++symAddrIter ;
  }
  delete allSymAddr ;
  // One final for bool selects
  list<CallStatement*>* allCalls = 
    collect_objects<CallStatement>(procDef->get_body()) ;
  list<CallStatement*>::iterator callIter = allCalls->begin() ;
  while(callIter != allCalls->end())
  {
    VariableSymbol* currentVar = (*callIter)->get_destination() ;
    if (currentVar != NULL &&
	replacementFields.find(currentVar) != replacementFields.end())
    {
      (*callIter)->set_destination(replacementFields[currentVar]) ;
    }
    ++callIter ;
  }
  delete allCalls ;
}
void CopyPropagationPass2::ProcessPossibleCopy(StoreVariableStatement* c)
{
  assert(c != NULL) ;
  // If this isn't a straight copy, just return
  LoadVariableExpression* replacement = 
    dynamic_cast<LoadVariableExpression*>(c->get_value()) ;
  if (replacement == NULL)
  {
    return ;
  }

  // If the variables are different types, don't propagate this away 
  //  (it is a cast)
  DataType* destType = c->get_destination()->get_type()->get_base_type() ;
  DataType* sourceType = replacement->get_source()->get_type()->get_base_type();
  if (!EquivalentTypes(destType, sourceType))
  {
    return ;
  }
     
  // Find all the reached uses
  BrickAnnote* reachedUses = 
    to<BrickAnnote>(c->lookup_annote_by_name("reached_uses")) ;

  assert(reachedUses != NULL) ;

  // Just in case we have no reached uses, we don't want to do 
  //  dead code elimination in this pass as well...
  bool removable = false ;

  Iter<SuifBrick*> useIter = reachedUses->get_brick_iterator() ;

  // First verify that we are the only definition for all of our uses.
  //  If we aren't then we can't make the replacement
  while(useIter.is_valid())
  {
    SuifObjectBrick* sob = to<SuifObjectBrick>(useIter.current()) ;
    assert (sob != NULL) ;
    LoadVariableExpression* nextLoad = 
      dynamic_cast<LoadVariableExpression*>(sob->get_object()) ;
    assert(nextLoad != NULL) ;
    if (IsOnlyDefinition(c, nextLoad) == false)
    {
      return ;
    }
    useIter.next() ;
  }

  // We also need to make sure that for each reached use, the copy is
  //  not redefined.  We do this by checking to make sure all of the
  //  definitions associated with it in the kill map are identical.
  //  This is a little conservative, but will make sure that no incorrect
  //  code is created.


  // Get the bit vector associated with all the reaching definitions
  //  coming into this statement
  BrickAnnote* inStatements = 
    dynamic_cast<BrickAnnote*>(c->lookup_annote_by_name("in_stmts")) ;
  assert(inStatements != NULL) ;
  SuifBrick* inBrick = inStatements->get_brick(0) ;
  assert(inBrick != NULL) ;
  SuifObjectBrick* inSOB = dynamic_cast<SuifObjectBrick*>(inBrick) ;
  assert(inSOB != NULL) ;
  SuifObject* inObj = inSOB->get_object() ;
  assert(inObj != NULL) ;
  BitVector2* inBits = dynamic_cast<BitVector2*>(inObj) ;
  assert(inBits != NULL) ;

  VariableSymbol* replacementVariable = replacement->get_source() ;
  assert(replacementVariable != NULL) ;

  list<std::pair<Statement*, int> >* definitions =killMap[replacementVariable];
  assert(definitions != NULL) ;

  list<bool> activeDefinitions ;
  list<std::pair<Statement*, int> >::iterator defIter = definitions->begin() ;
  while (defIter != definitions->end())
  {
    activeDefinitions.push_back(inBits->isMarked((*defIter).second)) ;
    ++defIter ;
  }

  useIter = reachedUses->get_brick_iterator() ;
  while (useIter.is_valid())
  {
    SuifObjectBrick* sob = to<SuifObjectBrick>(useIter.current()) ;
    assert(sob != NULL) ;
    LoadVariableExpression* nextLoad = 
      dynamic_cast<LoadVariableExpression*>(sob->get_object()) ;
    assert(nextLoad != NULL) ;
    SuifObject* loadParent = nextLoad->get_parent() ;
    while (dynamic_cast<Statement*>(loadParent) == NULL && loadParent != NULL)
    {
      loadParent = loadParent->get_parent() ;
    }
    assert(loadParent != NULL) ;
    Statement* parentStatement = dynamic_cast<Statement*>(loadParent) ;
    assert(parentStatement != NULL) ;
    BrickAnnote* parentInAnnote = dynamic_cast<BrickAnnote*>
      (parentStatement->lookup_annote_by_name("in_stmts")) ;
    assert(parentInAnnote != NULL) ;
    SuifBrick* parentInBrick = parentInAnnote->get_brick(0) ;
    assert(parentInBrick != NULL) ;
    SuifObjectBrick* parentInSOB = 
      dynamic_cast<SuifObjectBrick*>(parentInBrick) ;
    assert(parentInSOB != NULL) ;
    SuifObject* parentInObj = parentInSOB->get_object() ;
    assert(parentInObj != NULL) ;
    BitVector2* parentInBits = dynamic_cast<BitVector2*>(parentInObj) ;
    assert(parentInBits != NULL) ;

    defIter = definitions->begin() ;
    list<bool>::iterator activeIter = activeDefinitions.begin() ;
    while (defIter != definitions->end())
    {
      if ((*activeIter) != parentInBits->isMarked((*defIter).second))
      {
	// They are different, so don't do the replacement.
	return ;
      }
      ++activeIter ;
      ++defIter ;
    }

    useIter.next() ; 
  }
  
  // Now go through each reached use and replace it with the copy.
  //  Each reached use should be a load variable expression.
  //  We also have to deal with any feedback variables
  useIter = reachedUses->get_brick_iterator() ;
  while (useIter.is_valid())
  {
    SuifObjectBrick* sob = to<SuifObjectBrick>(useIter.current()) ;
    assert(sob != NULL) ;
    LoadVariableExpression* nextLoad = 
      dynamic_cast<LoadVariableExpression*>(sob->get_object()) ;
    assert(nextLoad != NULL) ;

    // Keep track of if we need to handle feedback variables
    HandleFeedbackVariables(nextLoad, replacement->get_source()) ;
    
    nextLoad->set_source(replacement->get_source()) ;

    removable = true ;

    useIter.next() ;
  }

  if (removable)
  {
    toBeRemoved.push_back(c) ;
  }  

}