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);
        }
    }
Exemplo n.º 2
0
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"));
                }
            }
        }
    }
}