Esempio n. 1
0
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;
}