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); } }