DataType* ExportPass::CloneDataType(DataType* t) { assert(t != NULL) ; PointerType* pointerClone = dynamic_cast<PointerType*>(t) ; ReferenceType* referenceClone = dynamic_cast<ReferenceType*>(t) ; ArrayType* arrayClone = dynamic_cast<ArrayType*>(t) ; if (pointerClone != NULL) { QualifiedType* refType = dynamic_cast<QualifiedType*>(pointerClone->get_reference_type()) ; assert(refType != NULL) ; DataType* cloneType = CloneDataType(refType->get_base_type()) ; assert(cloneType != NULL) ; return create_pointer_type(theEnv, IInteger(32), 0, create_qualified_type(theEnv, cloneType)) ; } if (referenceClone != NULL) { QualifiedType* refType = dynamic_cast<QualifiedType*>(referenceClone->get_reference_type()) ; assert(refType != NULL) ; DataType* clonedType = CloneDataType(refType->get_base_type()) ; return create_reference_type(theEnv, IInteger(32), 0, create_qualified_type(theEnv, clonedType)) ; } if (arrayClone != NULL) { QualifiedType* elementType = arrayClone->get_element_type() ; DataType* internalType = CloneDataType(elementType->get_base_type()) ; QualifiedType* finalQual = create_qualified_type(theEnv, internalType) ; return create_pointer_type(theEnv, IInteger(32), 0, finalQual) ; } return dynamic_cast<DataType*>(t->deep_clone()) ; }
static PointerType* pointer_to(SuifEnv *s, Type *type) { PointerType* pt = create_pointer_type(s, sizeof(void *),sizeof(void *),type); to<SymbolTable>( type->get_parent() ) -> append_symbol_table_object( pt ); return pt; }
DesignFlowStep_Status compute_implicit_calls::InternalExec() { tree_nodeRef node = TM->get_tree_node_const(function_id); function_decl * fd = GetPointer<function_decl>(node); if (!fd || !fd->body) { PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Node is not a function or it hasn't a body"); return DesignFlowStep_Status::UNCHANGED; } bool changed = false; std::list<std::pair<tree_nodeRef, unsigned int>> to_be_lowered_memset; unsigned int max_loop_id = 0; statement_list * sl = GetPointer<statement_list>(GET_NODE(fd->body)); THROW_ASSERT(sl, "Body is not a statement_list"); std::map<unsigned int, blocRef>::iterator it_bb, it_bb_end = sl->list_of_bloc.end(); for(it_bb = sl->list_of_bloc.begin(); it_bb != it_bb_end ; it_bb++) { if (it_bb->second->number == BB_ENTRY || it_bb->second->number == BB_EXIT) continue; max_loop_id = std::max(max_loop_id, it_bb->second->loop_id); for(const auto stmt : it_bb->second->CGetStmtList()) { tree_nodeRef tn = GET_NODE(stmt); if(tn->get_kind() == gimple_assign_K) { gimple_assign* gm = GetPointer<gimple_assign>(tn); INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing node " + tn->ToString()); /// check for implicit memset/memcpy calls tree_nodeRef op0 = GET_NODE(gm->op0); tree_nodeRef op1 = GET_NODE(gm->op1); unsigned int op0_type_index, op1_type_index; tree_nodeRef op0_type = tree_helper::get_type_node(op0, op0_type_index); tree_nodeRef op1_type = tree_helper::get_type_node(op1, op1_type_index); bool is_a_vector_bitfield = false; if(op1->get_kind() == bit_field_ref_K) { bit_field_ref* bfr = GetPointer<bit_field_ref>(op1); if(tree_helper::is_a_vector(TM, GET_INDEX_NODE(bfr->op0))) is_a_vector_bitfield = true; } bool load_candidate = (op1->get_kind() == bit_field_ref_K && !is_a_vector_bitfield) ||op1->get_kind() == component_ref_K || op1->get_kind() == indirect_ref_K || op1->get_kind() == misaligned_indirect_ref_K || op1->get_kind() == mem_ref_K || op1->get_kind() == array_ref_K || op1->get_kind() == target_mem_ref_K || op1->get_kind() == target_mem_ref461_K; if(op1->get_kind() == realpart_expr_K || op1->get_kind() == imagpart_expr_K) { enum kind code1 = GET_NODE(GetPointer<unary_expr>(op1)->op)->get_kind(); if((code1 == bit_field_ref_K && !is_a_vector_bitfield) || code1 == component_ref_K || code1 == indirect_ref_K || code1 == bit_field_ref_K || code1 == misaligned_indirect_ref_K || code1 == mem_ref_K || code1 == array_ref_K || code1 == target_mem_ref_K || code1 == target_mem_ref461_K) load_candidate = true; if(code1 == var_decl_K) load_candidate = true; } bool store_candidate = op0->get_kind() == bit_field_ref_K || op0->get_kind() == component_ref_K || op0->get_kind() == indirect_ref_K || op0->get_kind() == misaligned_indirect_ref_K || op0->get_kind() == mem_ref_K || op0->get_kind() == array_ref_K || op0->get_kind() == target_mem_ref_K || op0->get_kind() == target_mem_ref461_K; if(op0->get_kind() == realpart_expr_K || op0->get_kind() == imagpart_expr_K) { enum kind code0 = GET_NODE(GetPointer<unary_expr>(op0)->op)->get_kind(); if(code0 == component_ref_K || code0 == indirect_ref_K || code0 == bit_field_ref_K || code0 == misaligned_indirect_ref_K || code0 == mem_ref_K || code0 == array_ref_K || code0 == target_mem_ref_K || code0 == target_mem_ref461_K) store_candidate = true; if(code0 == var_decl_K) store_candidate = true; } if(!gm->clobber && !gm->init_assignment && op0_type && op1_type && ((op0_type->get_kind()== record_type_K && op1_type->get_kind()== record_type_K && op1->get_kind() != view_convert_expr_K) || (op0_type->get_kind()== union_type_K && op1_type->get_kind()== union_type_K && op1->get_kind() != view_convert_expr_K) || (op0_type->get_kind() == array_type_K) || (store_candidate && load_candidate) ) ) { changed = true; if(op1->get_kind() == constructor_K && GetPointer<constructor>(op1) && GetPointer<constructor>(op1)->list_of_idx_valu.size() == 0) { mem_ref * mr = GetPointer<mem_ref>(op0); THROW_ASSERT(mr, "unexpected condition"); unsigned int var = tree_helper::get_base_index(TM, GET_INDEX_NODE(mr->op0)); bool do_lowering = var != 0; if(do_lowering) { auto type_index = tree_helper::get_type_index(TM, var); const auto type_node = TM->get_tree_node_const(type_index); do_lowering = type_node->get_kind() == array_type_K; if(do_lowering) { const auto element_type = tree_helper::CGetElements(type_node); const auto element_type_kind = element_type->get_kind(); if(not (element_type_kind == boolean_type_K or element_type_kind == CharType_K or element_type_kind == enumeral_type_K or element_type_kind == integer_type_K or element_type_kind == pointer_type_K or element_type_kind == record_type_K)) { do_lowering = false; THROW_ASSERT(element_type_kind == array_type_K or element_type_kind == nullptr_type_K or element_type_kind == type_pack_expansion_K or element_type_kind == complex_type_K or element_type_kind == function_type_K or element_type_kind == lang_type_K or element_type_kind == method_type_K or element_type_kind == offset_type_K or element_type_kind == qual_union_type_K or element_type_kind == record_type_K or element_type_kind == reference_type_K or element_type_kind == set_type_K or element_type_kind == template_type_parm_K or element_type_kind == typename_type_K or element_type_kind == union_type_K or element_type_kind == vector_type_K or element_type_kind == void_type_K, element_type->get_kind_text()); } } } if(do_lowering) to_be_lowered_memset.push_front(std::make_pair(stmt,it_bb->second->number)); else { unsigned int memset_function_id = TM->function_index("__builtin_memset"); THROW_ASSERT(AppM->GetFunctionBehavior(memset_function_id)->GetBehavioralHelper()->has_implementation(), "inconsistent behavioral helper"); AppM->GetCallGraphManager()->AddCallPoint(function_id, memset_function_id, GET_INDEX_NODE(stmt), FunctionEdgeInfo::CallType::direct_call); } } else { unsigned int memcpy_function_id = TM->function_index("__builtin_memcpy"); THROW_ASSERT(AppM->GetFunctionBehavior(memcpy_function_id)->GetBehavioralHelper()->has_implementation(), "inconsistent behavioral helper"); AppM->GetCallGraphManager()->AddCallPoint(function_id, memcpy_function_id, GET_INDEX_NODE(stmt), FunctionEdgeInfo::CallType::direct_call); } } INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Analyzed node " + tn->ToString()); } } } /// do the memset transformations for(auto stmt_bb_pair : to_be_lowered_memset) { INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Transforming (" + STR(stmt_bb_pair.first->index) + ")" + STR(stmt_bb_pair.first)); auto BB1_index = stmt_bb_pair.second; auto BB1_block = sl->list_of_bloc[BB1_index]; ///create BBN1 const auto BBN1_block_index = (sl->list_of_bloc.rbegin())->first + 1; INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created BB" + STR(BBN1_block_index)); auto BBN1_block = blocRef(new bloc(BBN1_block_index)); sl->list_of_bloc[BBN1_block_index] = BBN1_block; max_loop_id++; BBN1_block->loop_id = max_loop_id; BBN1_block->schedule = BB1_block->schedule; ///Add BBN1 predecessor as BB1_index basic block BBN1_block->list_of_pred.push_back(BB1_index); BBN1_block->list_of_pred.push_back(BBN1_block_index); ///create BBN2 const auto BBN2_block_index = (sl->list_of_bloc.rbegin())->first + 1; INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created BB" + STR(BBN2_block_index)); auto BBN2_block = blocRef(new bloc(BBN2_block_index)); sl->list_of_bloc[BBN2_block_index] = BBN2_block; BBN2_block->loop_id = BB1_block->loop_id; BBN2_block->schedule = BB1_block->schedule; ///Add BBN2 predecessor as BBN1 basic block BBN2_block->list_of_pred.push_back(BBN1_block_index); ///Add BBN2 successor as BB1 basic block BBN2_block->list_of_succ = BB1_block->list_of_succ; /// fix true and false edges BBN2_block->true_edge = BB1_block->true_edge; BB1_block->true_edge = 0; BBN2_block->false_edge = BB1_block->false_edge; BB1_block->false_edge = 0; BB1_block->list_of_succ.clear(); BB1_block->list_of_succ.push_back(BBN1_block_index); ///Add BBN1 successor as succ basic block BBN1_block->list_of_succ.push_back(BBN1_block_index); BBN1_block->true_edge = BBN1_block_index; BBN1_block->list_of_succ.push_back(BBN2_block_index); BBN1_block->false_edge = BBN2_block_index; /// Fix BBN2 successors for(auto succ: BBN2_block->list_of_succ) { auto succ_block = sl->list_of_bloc[succ]; succ_block->list_of_pred.erase(std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), BB1_index)); succ_block->list_of_pred.push_back(BBN2_block_index); ///Update all the phis for(auto & phi : succ_block->CGetPhiList()) { auto gp = GetPointer<gimple_phi>(GET_NODE(phi)); for(auto & def_edge : gp->CGetDefEdgesList()) { if(def_edge.second == BB1_index) { gp->ReplaceDefEdge(TM, def_edge, gimple_phi::DefEdge(def_edge.first, BBN2_block_index)); } } } } ///The tree manipulation auto tree_man = tree_manipulationRef(new tree_manipulation(TM, parameters)); /// retrive the starting variable gimple_assign* ga = GetPointer<gimple_assign>(GET_NODE(stmt_bb_pair.first)); mem_ref * mr = GetPointer<mem_ref>(GET_NODE(ga->op0)); unsigned int var = tree_helper::get_base_index(TM, GET_INDEX_NODE(mr->op0)); tree_nodeRef init_var = mr->op0; const std::string srcp_default = ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number); auto type_index = tree_helper::get_type_index(TM, var); tree_nodeConstRef type_node = TM->CGetTreeNode(type_index); THROW_ASSERT(type_node->get_kind() == array_type_K, "unexpected condition"); while (type_node->get_kind() == array_type_K) type_node = tree_helper::CGetElements(type_node); tree_nodeRef offset_type = tree_man->create_size_type(); tree_nodeRef pt = tree_man->create_pointer_type(type_node); /// add a cast tree_nodeRef nop_init_var = tree_man->create_unary_operation(pt, init_var, srcp_default, nop_expr_K); tree_nodeRef nop_init_var_ga = tree_man->CreateGimpleAssign(pt, nop_init_var, BB1_index, srcp_default); init_var = GetPointer<gimple_assign>(GET_NODE(nop_init_var_ga))->op0; INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---adding cast statement " + GET_NODE(nop_init_var_ga)->ToString()); ///Create phi for the induction variable of BBN1 tree_nodeRef new_induction_var; ///The list of def edge which contains for the moment only the value coming from the forward edge std::vector<std::pair<tree_nodeRef, unsigned int> > list_of_def_edge; list_of_def_edge.push_back(std::pair<tree_nodeRef, unsigned int>(init_var, BB1_index)); auto phi = tree_man->create_phi_node(new_induction_var, list_of_def_edge, BBN1_block_index); BBN1_block->AddPhi(phi); gimple_phi* gp = GetPointer<gimple_phi>(GET_NODE(phi)); GetPointer<ssa_name>(GET_NODE(gp->res))->use_set = PointToSolutionRef(new PointToSolution()); GetPointer<ssa_name>(GET_NODE(gp->res))->use_set->variables.push_back(TM->GetTreeReindex(var)); /// compute the size of memory to be set with memset const auto dst_type = tree_helper::CGetType(GET_NODE(mr->op0)); const pointer_type * dst_ptr_t = GetPointer<const pointer_type>(dst_type); THROW_ASSERT(dst_ptr_t, "unexpected condition"); const auto dst_size = tree_helper::Size(dst_ptr_t->ptd); THROW_ASSERT(dst_size % 8 == 0, "unexpected condition"); const auto copy_byte_size = dst_size / 8; tree_nodeRef copy_byte_size_node = TM->CreateUniqueIntegerCst(static_cast<long long int >(copy_byte_size), GET_INDEX_NODE(offset_type)); tree_nodeRef pp = tree_man->create_binary_operation(pt, init_var, copy_byte_size_node, srcp_default, pointer_plus_expr_K); tree_nodeRef pp_ga = tree_man->CreateGimpleAssign(pt, pp, BB1_index, srcp_default); GetPointer<gimple_assign>(GET_NODE(pp_ga))->temporary_address = true; tree_nodeRef vd_limit = GetPointer<gimple_assign>(GET_NODE(pp_ga))->op0; GetPointer<ssa_name>(GET_NODE(vd_limit))->use_set = PointToSolutionRef(new PointToSolution()); GetPointer<ssa_name>(GET_NODE(vd_limit))->use_set->variables.push_back(TM->GetTreeReindex(var)); INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---adding statement " + GET_NODE(pp_ga)->ToString()); tree_nodeRef size_node = TM->CreateUniqueIntegerCst(static_cast<long long int >(tree_helper::Size(type_node)/8), GET_INDEX_NODE(offset_type)); tree_nodeRef pp_ind = tree_man->create_binary_operation(pt, gp->res, size_node, srcp_default, pointer_plus_expr_K); tree_nodeRef pp_ga_ind = tree_man->CreateGimpleAssign(pt, pp_ind, BBN1_block_index, srcp_default); GetPointer<gimple_assign>(GET_NODE(pp_ga_ind))->temporary_address = true; BBN1_block->PushBack(pp_ga_ind); tree_nodeRef vd_ind = GetPointer<gimple_assign>(GET_NODE(pp_ga_ind))->op0; GetPointer<ssa_name>(GET_NODE(vd_ind))->use_set = PointToSolutionRef(new PointToSolution()); GetPointer<ssa_name>(GET_NODE(vd_ind))->use_set->variables.push_back(TM->GetTreeReindex(var)); INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---adding statement " + GET_NODE(pp_ga_ind)->ToString()); GetPointer<gimple_phi>(GET_NODE(phi))->AddDefEdge(TM, gimple_phi::DefEdge(vd_ind, BBN1_block_index)); /// the comparison const auto boolean_type = tree_man->create_boolean_type(); const auto comparison = tree_man->create_binary_operation(boolean_type, vd_ind, vd_limit, srcp_default, ne_expr_K); tree_nodeRef comp_ga = tree_man->CreateGimpleAssign(boolean_type, comparison, BBN1_block_index, srcp_default); BBN1_block->PushBack(comp_ga); tree_nodeRef comp_res = GetPointer<gimple_assign>(GET_NODE(comp_ga))->op0; INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---comparison assign " + STR(comp_ga)); /// the gimple cond const auto gc = tree_man->create_gimple_cond(comp_res, srcp_default, BBN1_block_index); INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---gimple cond " + STR(gc)); /// restructure of the implicit memset statement tree_nodeRef zero_offset = TM->CreateUniqueIntegerCst(0, GET_INDEX_NODE(pt)); tree_nodeRef new_mem_ref = tree_man->create_binary_operation(TM->GetTreeReindex(type_node->index), gp->res, zero_offset, srcp_default, mem_ref_K); ga->op0 = new_mem_ref; tree_nodeRef zero_value = TM->CreateUniqueIntegerCst(0, type_node->index); ga->op1 = zero_value; const auto list_of_stmt = BB1_block->CGetStmtList(); bool found_memset_statement = false; ///We must use pointer since we are erasing elements in the list for(auto statement = list_of_stmt.begin(); statement != list_of_stmt.end(); statement++) { if(GET_INDEX_NODE(*statement) == GET_INDEX_CONST_NODE(stmt_bb_pair.first)) { /// move var = {}; to BBN1 found_memset_statement = true; const auto temp_statement = *statement; ///Going one step step forward to avoid invalidation of the pointer statement++; ///Moving statement BB1_block->RemoveStmt(temp_statement); BBN1_block->PushBack(temp_statement); ///Going one step back since pointer is already increment in for loop statement--; } else if(found_memset_statement) { /// move (xxxxb)* to BBN2 const auto temp_statement = *statement; ///Going one step step forward to avoid invalidation of the pointer statement++; ///Moving statement BB1_block->RemoveStmt(temp_statement); BBN2_block->PushBack(temp_statement); ///Going one step back since pointer is already increment in for loop statement--; } } THROW_ASSERT(found_memset_statement, "unexpected condition"); BB1_block->PushBack(nop_init_var_ga); BB1_block->PushBack(pp_ga); BBN1_block->PushBack(gc); INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Transformed " + STR(stmt_bb_pair.first)); } if (debug_level >= DEBUG_LEVEL_PEDANTIC or parameters->getOption<bool>(OPT_print_dot)) AppM->CGetCallGraphManager()->CGetCallGraph()->WriteDot("compute_implicit_calls" + GetSignature() + ".dot"); return changed ? DesignFlowStep_Status::SUCCESS : DesignFlowStep_Status::UNCHANGED; }