VariableSymbol *build_string_constant_variable(SuifEnv *env,const char *string) {
    TypeBuilder *tb = (TypeBuilder *)
        env->get_object_factory(TypeBuilder::get_class_name());
    IntegerType *char_type =
        tb->get_integer_type(sizeof(char)*BITSPERBYTE,
                           sizeof(char)*BITSPERBYTE,true);

    size_t len = 0;
    while (string[len])
	len ++;
    QualifiedType *q_char_type = tb->get_qualified_type(char_type);
    ArrayType *string_literal_type =
      tb->get_array_type(q_char_type,0,len + 1);
   
    MultiValueBlock *string_literal_initialization =
            create_multi_value_block(env,string_literal_type);
    for (size_t char_num = 0; char_num <= len; ++char_num) {
        string_literal_initialization->add_sub_block(
                char_num,
                create_expression_value_block(
			env,
                   	create_int_constant( 
				env,char_type,string[char_num])));
        }
    return build_initialized_variable(env,emptyLString,string_literal_type,
				      string_literal_initialization,true);
    }
VariableSymbol *build_initialized_variable(
        SuifEnv *env,
	const LString &name,
	DataType *type,
	ValueBlock *vb,
	bool make_static) {
    TypeBuilder *tb = (TypeBuilder *)
        env->get_object_factory(TypeBuilder::get_class_name());
    FileSetBlock *fsb = env->get_file_set_block();
    suif_assert_message(fsb->get_file_block_count() == 1,("File is ambiguous"));
    FileBlock *fb = fsb->get_file_block(0);
    
    BasicSymbolTable *symtab = to<BasicSymbolTable>(fb->get_symbol_table());
    DefinitionBlock *def  = fb->get_definition_block ();
    QualifiedType *q_type = tb->get_qualified_type(type);

    VariableSymbol *var = create_variable_symbol(
                env,q_type, name, false );
    symtab->append_symbol_table_object(var);
    VariableDefinition *vardef =
            create_variable_definition(env,var,type->get_bit_alignment(),
					vb,make_static);
    def->append_variable_definition(vardef);
    return var;
    }
Walker::ApplyStatus NonConstBoundArrayTypeWalker::operator () (SuifObject *x) {
    ArrayTypeProxy type(to<DataType>(x));
    if (!type.has_non_const_bounds())
	return Walker::Continue;    
    Type *rep_type = _type_builder->get_array_type(_type_builder->get_qualified_type(type.get_element_type()),0,1);
    set_address(rep_type);
    to<BasicSymbolTable>(x->get_parent())->remove_symbol_table_object(
 		to<SymbolTableObject>(x));
    return Walker::Replaced;
}
Walker::ApplyStatus sctis_multi_way_branch_statement_walker::operator () (SuifObject *x) {
    SuifEnv *env = get_env();
    MultiWayBranchStatement *multi_way_stmt = to<MultiWayBranchStatement>(x);
    ProcedureDefinition *proc_def = get_procedure_definition(multi_way_stmt);
    TypeBuilder *tb = get_type_builder(env);

    BrickAnnote *end_label_annote = to<BrickAnnote>(multi_way_stmt->lookup_annote_by_name("end_label"));
    SuifObjectBrick *sob = to<SuifObjectBrick>(end_label_annote->get_brick(0));
    CodeLabelSymbol *end_label_sym = to<CodeLabelSymbol>(sob->get_object());

    Expression *decision_expr = multi_way_stmt->get_decision_operand();

    CodeLabelSymbol *default_label_sym = multi_way_stmt->get_default_target();

    Statement *replacement = get_statement_block_btw_labels(proc_def, default_label_sym, end_label_sym);

    cout << "ADDED " << print_statement(replacement);

    for(Iter<indexed_list<IInteger, CodeLabelSymbol*>::pair> iter = multi_way_stmt->get_case_iterator();
            iter.is_valid(); iter.next()) {

        indexed_list<IInteger, CodeLabelSymbol*>::pair case_pair = iter.current();

        Expression *condition_expr = create_binary_expression(env,
                                     tb->get_boolean_type(),
                                     String("is_equal_to"),
                                     to<Expression>(deep_suif_clone(decision_expr)),
                                     create_int_constant(env,
                                             decision_expr->get_result_type(),
                                             case_pair.first));

        Statement *then_stmt = get_statement_block_btw_labels(proc_def, case_pair.second, end_label_sym);
        print_statement(then_stmt);

        replacement = create_if_statement(env, condition_expr, then_stmt, replacement);
    }

    Statement *next_stmt = get_next_statement(multi_way_stmt);
    bool is_removal_complete = 0;
    while(!is_removal_complete && next_stmt != NULL) {
        if(is_a<LabelLocationStatement>(next_stmt)) {
            if((to<LabelLocationStatement>(next_stmt))->get_defined_label() == end_label_sym)
                is_removal_complete = 1;
        }
        remove_statement(next_stmt);
        next_stmt = get_next_statement(multi_way_stmt);
    }

    multi_way_stmt->get_parent()->replace(multi_way_stmt, replacement);

    set_address(replacement);
    return Walker::Replaced;
}
Example #5
0
IntConstant* build_vtbl_slot_count_int_constant( SuifEnv* env,
						 ClassType* owning_class )
{
  TypeBuilder* tb = get_type_builder( env );

  IntConstant* icnst =
    ::create_int_constant( env,
			   tb->get_integer_type( true ), // result_type
			   IInteger() // value: inserted later
			   );
  attach_vtbl_slot_count_annote( env, icnst, owning_class );
  return icnst;
}
Example #6
0
IntConstant* build_vtbl_slot_int_constant( SuifEnv* env,
					   InstanceMethodSymbol* msym )
{
  TypeBuilder* tb = get_type_builder( env );

  IntConstant* icnst =
    ::create_int_constant( env,
			   tb->get_integer_type( true ), // result_type
			   IInteger() // value: inserted later
			   );
  attach_vtbl_slot_annote( env, icnst, msym );
  return icnst;
}
Example #7
0
TypePtr Type::newType(const std::wstring& name, Category category, const TypeDeclarationPtr& reference, const TypePtr& parentType, const std::vector<TypePtr>& protocols, const GenericDefinitionPtr& generic)
{
    assert(!name.empty());
    TypeBuilder* ret = new TypeBuilder(category);
    ret->name = name;
    ret->reference = reference;
    ret->parentType = parentType;
    ret->protocols = protocols;
    ret->genericDefinition = generic;
    if(parentType)
        ret->addParentTypesFrom(parentType);
    for(const TypePtr& t : protocols)
    {
        ret->addParentTypesFrom(t);
    }
    if(parentType)
        ret->inheritantDepth = parentType->inheritantDepth + 1;
    return TypePtr(ret);
}
ITypeBuilder* TypeBuilder::create( TypeKind kind, INamespace* ns, const std::string& name )
{
	TypeBuilder* tb = NULL;
	switch( kind )
	{
	case TK_ENUM:			tb = new EnumBuilder;			break;
	case TK_EXCEPTION:		tb = new ExceptionTypeBuilder;	break;
	case TK_STRUCT:			tb = new StructBuilder;			break;
	case TK_NATIVECLASS:	tb = new NativeClassBuilder;	break;
	case TK_INTERFACE:		tb = new InterfaceBuilder;		break;
	case TK_COMPONENT:		tb = new ComponentBuilder;		break;
	default:
		assert( false );
	}

	assert( tb );
	tb->initialize( ns, name );

	return tb;
}
static Expression *build_empty_expression(DataType *t) {
  SuifEnv *s = t->get_suif_env();

  suif_assert_message(!is_kind_of<GroupType>(t),
		      ("build_empty_expression:: can not handle GroupType"));
  if (is_kind_of<VoidType>(t))
    return(NULL);

  if (is_kind_of<IntegerType>(t)) {
    IntConstant *c = create_int_constant(s, t, IInteger(0));
    return c;
  }
  // This works for Int, Float, Enum, pointers
  TypeBuilder *tb = get_type_builder(s);
  
  IntegerType *it = tb->get_integer_type();
  IntConstant *c = create_int_constant(s, it, IInteger(0));
  Expression *cvt = create_unary_expression(s, t,  k_convert, c);
  return(cvt);
}
Walker::ApplyStatus dste_call_statement_walker2::operator () (SuifObject *x) {
	SuifEnv *env = get_env();
	CallStatement *call_stmt = to<CallStatement>(x);

	SymbolAddressExpression *callee_address = to<SymbolAddressExpression>(call_stmt->get_callee_address());
	ProcedureSymbol *proc_symbol = to<ProcedureSymbol>(callee_address->get_addressed_symbol());
	String called_proc_name = proc_symbol->get_name();
	
	if(called_proc_name == String("ROCCC_lookup_in_state_table")){

 	   Expression *argument_expr = call_stmt->get_argument(0);
	   if(is_a<UnaryExpression>(argument_expr))
	      argument_expr = (to<UnaryExpression>(argument_expr))->get_source();
	   int st_id = (to<IntConstant>(argument_expr))->get_value().c_int();

	   suif_map<int, ST*>::iterator iter = state_table_defs->find(st_id);
	   if(iter == state_table_defs->end())
	      return Walker::Continue;
	
	   ST* state_table_def = (*iter).second;
	   int pattern_length = state_table_def->get_length();
	   int state_count = state_table_def->get_state_count();
	   int alphabet_count = state_table_def->get_alphabet_count();
	   int start_state = state_table_def->get_start_state();
	   int error_state = state_table_def->get_error_state();
	   int final_state = state_table_def->get_final_state();

	   VariableSymbol *char_set_array_sym = state_table_def->get_char_set_sym();
	   DataType *stream_data_type = get_array_element_type(char_set_array_sym);
	   QualifiedType *qualed_stream_data_type = retrieve_qualified_type(stream_data_type);

	   VariableSymbol *state_table_sym = state_table_def->get_state_table_sym();
	   DataType *dfa_state_data_type = get_array_element_type(state_table_sym);
	   QualifiedType *qualed_dfa_state_type = retrieve_qualified_type(dfa_state_data_type);

	   StatementList *replacement = create_statement_list(env);

 	   argument_expr = call_stmt->get_argument(1);
	   argument_expr->set_parent(0);
	   if(is_a<UnaryExpression>(argument_expr))
	      argument_expr = (to<UnaryExpression>(argument_expr))->get_source();

	   VariableSymbol* input_char_sym = new_anonymous_variable(env, proc_def_body, qualed_stream_data_type);
	   name_variable(input_char_sym, "ic");

	   StoreVariableStatement *store_var_stmt = create_store_variable_statement(env, input_char_sym, argument_expr);
	   replacement->append_statement(store_var_stmt);

           TypeBuilder *tb = get_type_builder(env);
           SymbolTable *external_symbol_table = get_external_symbol_table(get_procedure_definition(call_stmt));

           list<QualifiedType*> cam_proc_argument_types;
	   for(int j = 0; j < alphabet_count+1; j++)
	       cam_proc_argument_types.push_back(qualed_stream_data_type);
           DataType *cam_return_type;
           int cam_return_bit_size = get_unsigned_bit_size(alphabet_count);
	   cam_return_type = tb->get_integer_type(cam_return_bit_size, cam_return_bit_size, 0);
           cam_return_type->set_name(String("ROCCC_int") + String(cam_return_bit_size));
           CProcedureType *cam_proc_type = tb->get_c_procedure_type(cam_return_type, cam_proc_argument_types);
	   ProcedureSymbol *cam_proc_sym = create_procedure_symbol(env, cam_proc_type, String("ROCCC_cam") + String(alphabet_count));
           external_symbol_table->add_symbol(cam_proc_sym);

	   VariableSymbol* alphabet_index_sym = new_anonymous_variable(env, proc_def_body, retrieve_qualified_type(cam_return_type));
	   name_variable(alphabet_index_sym, "ais");

           SymbolAddressExpression *cam_proc_sym_expr = create_symbol_address_expression(env, tb->get_pointer_type(cam_proc_type), cam_proc_sym);
           CallStatement *cam_macro_stmt = create_call_statement(env, alphabet_index_sym, cam_proc_sym_expr);
	   for(int j = 0; j < alphabet_count; j++){

	       Expression *cam_argument_expr = create_symbol_address_expression(env, char_set_array_sym->get_type()->get_base_type(), char_set_array_sym);
	       cam_argument_expr = create_array_reference_expression(env, stream_data_type, cam_argument_expr, 
								create_int_constant(env, tb->get_integer_type(), IInteger(j)));
	       cam_argument_expr = create_load_expression(env, stream_data_type, cam_argument_expr);

               cam_macro_stmt->append_argument(cam_argument_expr);
	   }

           cam_macro_stmt->append_argument(create_load_variable_expression(env, stream_data_type, input_char_sym));
 	   replacement->append_statement(cam_macro_stmt);

	   suif_vector<VariableSymbol*>* state_column_vars = new suif_vector<VariableSymbol*>;
	   for(int i = 0; i < state_count; i++){

 	       VariableSymbol* state_column_sym = new_anonymous_variable(env, proc_def_body, qualed_dfa_state_type);
	       name_variable(state_column_sym, "st");
	       state_column_vars->push_back(state_column_sym);
	   }

           list<QualifiedType*> mux_proc_argument_types;
	   for(int j = 0; j < alphabet_count; j++)
	       mux_proc_argument_types.push_back(qualed_dfa_state_type);
	   mux_proc_argument_types.push_back(retrieve_qualified_type(cam_return_type));
           CProcedureType *mux_proc_type = tb->get_c_procedure_type(dfa_state_data_type, mux_proc_argument_types);
	   ProcedureSymbol *mux_proc_sym = create_procedure_symbol(env, mux_proc_type, String("ROCCC_mux") + String(alphabet_count));
           external_symbol_table->add_symbol(mux_proc_sym);

           ArrayType *state_table_array_type = to<ArrayType>(state_table_sym->get_type()->get_base_type());
	   for(int i = 0; i < state_count; i++){

	       if(i == error_state){
	          StoreVariableStatement *state_column_var_init_stmt = create_store_variable_statement(env, state_column_vars->at(i), 
									create_int_constant(env, tb->get_integer_type(), IInteger(i)));
	          replacement->append_statement(state_column_var_init_stmt);
		  continue;
	       }

               SymbolAddressExpression *mux_proc_sym_expr = create_symbol_address_expression(env, tb->get_pointer_type(mux_proc_type), mux_proc_sym);
               CallStatement *mux_macro_stmt = create_call_statement(env, state_column_vars->at(i), mux_proc_sym_expr);

	       for(int j = 0; j < alphabet_count; j++){
	           Expression *mux_argument_expr = create_symbol_address_expression(env, state_table_array_type, state_table_sym);
	           mux_argument_expr = create_array_reference_expression(env, state_table_array_type->get_element_type()->get_base_type(),
		  					mux_argument_expr, create_int_constant(env, tb->get_integer_type(), IInteger(i)));
	           mux_argument_expr = create_array_reference_expression(env, dfa_state_data_type, mux_argument_expr, 
							create_int_constant(env, tb->get_integer_type(), IInteger(j)));
	           mux_argument_expr = create_load_expression(env, dfa_state_data_type, mux_argument_expr);

                   mux_macro_stmt->append_argument(mux_argument_expr);
	       }
	   
               mux_macro_stmt->append_argument(create_load_variable_expression(env, cam_return_type, alphabet_index_sym));
	       replacement->append_statement(mux_macro_stmt);
	   }

	   suif_vector<VariableSymbol*>* current_state_vars = new suif_vector<VariableSymbol*>;
	   suif_vector<VariableSymbol*>* next_state_vars = new suif_vector<VariableSymbol*>;

	   StatementList *var_init_stmt_list = create_statement_list(env);
	   for(int i = 0; i < pattern_length; i++){

 	       VariableSymbol* current_state_sym = new_anonymous_variable(env, proc_def_body, qualed_dfa_state_type);
	       name_variable(current_state_sym, "cs");
               BrickAnnote *feedback_level_annote = create_brick_annote(env, "feedback_level");
               current_state_sym->append_annote(feedback_level_annote);
               feedback_level_annote->insert_brick(0, create_integer_brick(env, IInteger(0)));
	       current_state_vars->push_back(current_state_sym);

	       StoreVariableStatement *init_var_stmt = create_store_variable_statement(env, current_state_sym, 
							create_int_constant(env, dfa_state_data_type, IInteger(start_state)));
	       var_init_stmt_list->append_statement(init_var_stmt);

 	       VariableSymbol* next_state_sym = new_anonymous_variable(env, proc_def_body, qualed_dfa_state_type);
	       name_variable(next_state_sym, "ns");
	       next_state_vars->push_back(next_state_sym);
	   }
	   insert_statement_before(get_enclosing_c_for_stmt(call_stmt), var_init_stmt_list);

           mux_proc_argument_types.empty();
	   for(int j = 0; j < state_count+1; j++)
	       mux_proc_argument_types.push_back(qualed_dfa_state_type);
           mux_proc_type = tb->get_c_procedure_type(dfa_state_data_type, mux_proc_argument_types);
           mux_proc_sym = create_procedure_symbol(env, mux_proc_type, String("ROCCC_mux") + String(state_count));
           external_symbol_table->add_symbol(mux_proc_sym);

	   for(int i = 0; i < pattern_length; i++){

               SymbolAddressExpression *mux_proc_sym_expr = create_symbol_address_expression(env, tb->get_pointer_type(mux_proc_type), mux_proc_sym);
               CallStatement *mux_macro_stmt = create_call_statement(env, next_state_vars->at(i), mux_proc_sym_expr);

	       for(int k = 0; k < state_count; k++)
	           mux_macro_stmt->append_argument(create_load_variable_expression(env, dfa_state_data_type, state_column_vars->at(k)));

	       mux_macro_stmt->append_argument(create_load_variable_expression(env, dfa_state_data_type, current_state_vars->at(i)));
	       replacement->append_statement(mux_macro_stmt);
	   }

           Expression *equality_check_expr = create_binary_expression(env, tb->get_boolean_type(), String("is_equal_to"),
                                                create_load_variable_expression(env, dfa_state_data_type, next_state_vars->at(0)),
                                                create_int_constant(env, dfa_state_data_type, IInteger(final_state)));
           VariableSymbol *destination_sym = call_stmt->get_destination();
	   StoreVariableStatement *result_stmt = create_store_variable_statement(env, destination_sym, equality_check_expr); 
	   replacement->append_statement(result_stmt);
           for(int i = 1; i < pattern_length; i++){
               equality_check_expr = create_binary_expression(env, tb->get_boolean_type(), String("is_equal_to"),
                                                create_load_variable_expression(env, dfa_state_data_type, next_state_vars->at(i)),
                                                create_int_constant(env, dfa_state_data_type, IInteger(final_state)));
               Expression *result_expr = create_binary_expression(env, tb->get_boolean_type(), String("logical_or"),
                                                create_load_variable_expression(env, tb->get_boolean_type(), destination_sym),
                                                equality_check_expr);
	       result_stmt = create_store_variable_statement(env, destination_sym, result_expr); 
	       replacement->append_statement(result_stmt);
           }           
                    
           for(int i = 0; i < pattern_length-1; i++){
               
               StoreVariableStatement *store_var_stmt = create_store_variable_statement(env, current_state_vars->at(i+1),
                                        create_load_variable_expression(env, dfa_state_data_type, next_state_vars->at(i)));
               replacement->append_statement(store_var_stmt);
           }   

  	   call_stmt->get_parent()->replace(call_stmt, replacement);
	   return Walker::Truncate;
  	}

        return Walker::Continue;
}
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);
        }
    }
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"));
                }
            }
        }
    }
}
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
    }
}