PandA-2024.02
FunctionCallTypeCleanup.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
42 
43 #include "Parameter.hpp"
44 
45 #include "call_graph_manager.hpp"
46 
47 #include "tree_basic_block.hpp"
48 #include "tree_helper.hpp"
49 #include "tree_manager.hpp"
50 #include "tree_manipulation.hpp"
51 #include "tree_node.hpp"
52 #include "tree_reindex.hpp"
53 
54 #include "application_manager.hpp"
55 
56 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
57 #include "function_behavior.hpp"
58 #include "string_manipulation.hpp" // for GET_CLASS
59 
61  unsigned int _function_id,
62  const DesignFlowManagerConstRef _design_flow_manager)
63  : FunctionFrontendFlowStep(_AppM, _function_id, FUNCTION_CALL_TYPE_CLEANUP, _design_flow_manager, Param)
64 {
65  debug_level = Param->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
66 }
67 
69 
71 {
72 }
73 
76 {
78  switch(relationship_type)
79  {
81  {
82  relationships.insert(std::make_pair(CHECK_SYSTEM_TYPE, SAME_FUNCTION));
83  relationships.insert(std::make_pair(COMPUTE_IMPLICIT_CALLS, SAME_FUNCTION));
84  relationships.insert(std::make_pair(FIX_STRUCTS_PASSED_BY_VALUE, CALLED_FUNCTIONS));
85  relationships.insert(std::make_pair(FUNCTION_ANALYSIS, WHOLE_APPLICATION));
86  relationships.insert(std::make_pair(IR_LOWERING, SAME_FUNCTION));
87  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
88  break;
89  }
91  {
92  relationships.insert(std::make_pair(REMOVE_CLOBBER_GA, SAME_FUNCTION));
93  break;
94  }
96  {
97  break;
98  }
99  default:
100  {
101  THROW_UNREACHABLE("");
102  }
103  }
104  return relationships;
105 }
106 
108 {
109  bool changed = false;
110  const auto TM = AppM->get_tree_manager();
111  const auto tree_man = tree_manipulationRef(new tree_manipulation(TM, parameters, AppM));
112  const auto tn = TM->CGetTreeNode(function_id);
113  const auto fd = GetPointerS<const function_decl>(tn);
114  THROW_ASSERT(fd && fd->body, "Node is not a function or it hasn't a body");
115  const auto sl = GetPointerS<const statement_list>(GET_CONST_NODE(fd->body));
116  THROW_ASSERT(sl, "Body is not a statement_list");
117  const auto CGMan = AppM->CGetCallGraphManager();
118  const auto called_body_fun_ids = CGMan->GetReachedFunctionsFrom(function_id);
119 
120  for(const auto& block : sl->list_of_bloc)
121  {
122  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining BB" + STR(block.first));
123  for(const auto& stmt : block.second->CGetStmtList())
124  {
126  "-->Examining statement " + GET_CONST_NODE(stmt)->ToString());
127  if(GET_CONST_NODE(stmt)->get_kind() == gimple_assign_K)
128  {
129  const auto ga = GetPointerS<const gimple_assign>(GET_CONST_NODE(stmt));
130  const auto srcp_default = ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
131  const auto code0 = GET_CONST_NODE(ga->op0)->get_kind();
132  const auto code1 = GET_CONST_NODE(ga->op1)->get_kind();
133 
134  THROW_ASSERT(!ga->clobber, "");
135  if(code1 == call_expr_K || code1 == aggr_init_expr_K)
136  {
137  const auto ce = GetPointerS<call_expr>(GET_NODE(ga->op1));
138  if(GET_CONST_NODE(ce->fn)->get_kind() == addr_expr_K)
139  {
140  const auto addr_node = GET_CONST_NODE(ce->fn);
141  const auto ae = GetPointerS<const addr_expr>(addr_node);
142  const auto fu_decl_node = GET_CONST_NODE(ae->op);
143  THROW_ASSERT(fu_decl_node->get_kind() == function_decl_K, "node " + STR(fu_decl_node) +
144  " is not function_decl but " +
145  fu_decl_node->get_kind_text());
146  const auto ret_type_node = tree_helper::GetFunctionReturnType(fu_decl_node);
148  "---is a call_expr with LHS " + GET_CONST_NODE(ga->op0)->ToString());
150  "---the called function returns type " + STR(ret_type_node));
151  if(code0 == ssa_name_K)
152  {
153  const auto assigned_ssa_type_node = tree_helper::CGetType(ga->op0);
155  "---the assigned ssa_name " + STR(GET_CONST_NODE(ga->op0)) + " has type " +
156  STR(assigned_ssa_type_node));
157  if(!tree_helper::IsSameType(ret_type_node, assigned_ssa_type_node))
158  {
159  const auto new_ssa =
160  tree_man->create_ssa_name(tree_nodeRef(), ret_type_node, tree_nodeRef(), tree_nodeRef());
162  "---create ssa " + GET_CONST_NODE(new_ssa)->ToString());
163 
164  const auto ga_nop = tree_man->CreateNopExpr(new_ssa, assigned_ssa_type_node, tree_nodeRef(),
167  "---create nop " + GET_CONST_NODE(ga_nop)->ToString());
168 
169  const auto cast_ga = GetPointerS<const gimple_assign>(GET_CONST_NODE(ga_nop));
170  TM->ReplaceTreeNode(ga_nop, cast_ga->op0, ga->op0);
172  "---fix nop " + GET_CONST_NODE(ga_nop)->ToString());
173 
174  TM->ReplaceTreeNode(stmt, ga->op0, new_ssa);
176  "---update call " + GET_CONST_NODE(stmt)->ToString());
177 
178  block.second->PushAfter(ga_nop, stmt, AppM);
180  "---insert nop " + GET_CONST_NODE(ga_nop)->ToString());
181  changed = true;
182  }
183  }
184  const auto called_id = GET_INDEX_NODE(ae->op);
185  if(called_body_fun_ids.find(called_id) != called_body_fun_ids.end())
186  {
187  changed |= ParametersTypeCleanup(TM, tree_man, block.second, stmt, ce->args, srcp_default);
188  }
189  else
190  {
191  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Function does not have a body");
192  }
193  }
194  else if(GET_CONST_NODE(ce->fn)->get_kind() != ssa_name_K)
195  {
196  THROW_UNREACHABLE("call node " + STR(GET_CONST_NODE(ce->fn)) + " is a " +
197  GET_CONST_NODE(ce->fn)->get_kind_text());
198  }
199  }
200  }
201  else if(GET_CONST_NODE(stmt)->get_kind() == gimple_call_K)
202  {
203  const auto gc = GetPointerS<gimple_call>(GET_NODE(stmt));
204  if(GET_CONST_NODE(gc->fn)->get_kind() == addr_expr_K)
205  {
206  const auto addr_node = GET_CONST_NODE(gc->fn);
207  const auto ae = GetPointerS<const addr_expr>(addr_node);
208  THROW_ASSERT(GET_CONST_NODE(ae->op)->get_kind() == function_decl_K,
209  "node " + STR(GET_CONST_NODE(ae->op)) + " is not function_decl but " +
210  GET_CONST_NODE(ae->op)->get_kind_text());
211  const auto called_id = GET_INDEX_CONST_NODE(ae->op);
212  if(called_body_fun_ids.find(called_id) != called_body_fun_ids.end())
213  {
214  const auto srcp_default =
215  gc->include_name + ":" + STR(gc->line_number) + ":" + STR(gc->column_number);
216  changed |= ParametersTypeCleanup(TM, tree_man, block.second, stmt, gc->args, srcp_default);
217  }
218  else
219  {
220  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Function does not have a body");
221  }
222  }
223  else if(GET_CONST_NODE(gc->fn)->get_kind() != ssa_name_K)
224  {
225  THROW_UNREACHABLE("call node " + STR(GET_CONST_NODE(gc->fn)) + " is a " +
226  GET_CONST_NODE(gc->fn)->get_kind_text());
227  }
228  }
230  "<--Examined statement " + GET_CONST_NODE(stmt)->ToString());
231  }
232  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined BB" + STR(block.first));
233  }
234 
235  if(changed)
236  {
237  function_behavior->UpdateBBVersion();
238  }
240 }
241 
243  const blocRef& block, const tree_nodeRef& stmt,
244  std::vector<tree_nodeRef>& args, const std::string& srcp) const
245 {
246  bool changed = false;
247  unsigned arg_n = 0;
248  auto arg_it = args.cbegin();
249  for(; arg_it != args.cend(); arg_it++, arg_n++)
250  {
252  "-->Examining arg " + GET_CONST_NODE(*arg_it)->ToString() + " " +
253  GET_CONST_NODE(*arg_it)->get_kind_text());
254  const auto formal_type = tree_helper::GetFormalIth(stmt, arg_n);
255  const auto actual_type = tree_helper::CGetType(*arg_it);
257  "---formal type = " + GET_CONST_NODE(formal_type)->get_kind_text() + "\t" + STR(formal_type));
259  "---actual type = " + GET_CONST_NODE(actual_type)->get_kind_text() + "\t" + STR(actual_type));
260  tree_nodeRef ga_cleanup = nullptr;
261  if((GET_CONST_NODE(*arg_it)->get_kind() == integer_cst_K || GET_CONST_NODE(*arg_it)->get_kind() == ssa_name_K) &&
262  !tree_helper::IsSameType(formal_type, actual_type))
263  {
264  ga_cleanup = tree_man->CreateNopExpr(*arg_it, TM->CGetTreeReindex(formal_type->index), tree_nodeRef(),
266  }
267  else if(GET_CONST_NODE(*arg_it)->get_kind() == addr_expr_K || GET_CONST_NODE(*arg_it)->get_kind() == nop_expr_K ||
268  GET_CONST_NODE(*arg_it)->get_kind() == view_convert_expr_K)
269  {
270  const auto parm_ue = GetPointerS<const unary_expr>(GET_CONST_NODE(*arg_it));
271  const auto ue_expr = tree_man->create_unary_operation(
272  formal_type, parm_ue->op, srcp,
273  GET_CONST_NODE(*arg_it)->get_kind());
274  ga_cleanup =
275  tree_man->CreateGimpleAssign(formal_type, tree_nodeRef(), tree_nodeRef(), ue_expr, function_id, srcp);
276  }
277  if(ga_cleanup)
278  {
280  "---adding statement " + GET_CONST_NODE(ga_cleanup)->ToString());
281  block->PushBefore(ga_cleanup, stmt, AppM);
283  "---old call statement " + GET_CONST_NODE(stmt)->ToString());
284  const auto new_ssa = GetPointerS<const gimple_assign>(GET_CONST_NODE(ga_cleanup))->op0;
285  unsigned int k = 0;
286  auto tmp_arg_it = args.begin();
287  for(; tmp_arg_it != args.end(); tmp_arg_it++, k++)
288  {
289  if(GET_INDEX_CONST_NODE(*arg_it) == GET_INDEX_CONST_NODE(*tmp_arg_it) &&
290  tree_helper::GetFormalIth(stmt, k)->index == formal_type->index)
291  {
292  TM->RecursiveReplaceTreeNode(*tmp_arg_it, *tmp_arg_it, new_ssa, stmt, false);
293  tmp_arg_it = std::next(args.begin(), static_cast<int>(k));
294  arg_it = std::next(args.begin(), static_cast<int>(arg_n));
295  continue;
296  }
297  }
299  "---new call statement " + GET_CONST_NODE(stmt)->ToString());
300  THROW_ASSERT(k, "");
301  changed = true;
302  }
304  }
305  return changed;
306 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
static bool IsSameType(const tree_nodeConstRef &tn0, const tree_nodeConstRef &tn1)
Given two nodes tells if they have same base type (const is not considered: const double == double) ...
static tree_nodeConstRef GetFormalIth(const tree_nodeConstRef &obj, unsigned int parm_index)
Return the type of the ith formal parameter in case index_obj is a call_expr.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
File containing functions and utilities to support the printing of debug messagges.
Step successfully executed.
const tree_nodeRef CGetTreeReindex(const unsigned int i) const
Return a tree_reindex wrapping the i-th tree_node.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
struct definition of the source position.
Definition: tree_node.hpp:832
RelationshipType
The relationship type.
Source must be executed to satisfy target.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
~FunctionCallTypeCleanup() override
Destructor.
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:361
Data structure describing a basic block at tree level.
FunctionCallTypeCleanup(const ParameterConstRef Param, const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
tree_nodeRef create_unary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op, const std::string &srcp, enum kind operation_kind) const
EXPRESSION_TREE_NODES.
tree_nodeRef CreateGimpleAssign(const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, const tree_nodeRef &op, unsigned int function_decl_nid, const std::string &srcp) const
Create gimple assignment.
bool ParametersTypeCleanup(const tree_managerRef &TM, const tree_manipulationRef &tree_man, const blocRef &block, const tree_nodeRef &stmt, std::vector< tree_nodeRef > &args, const std::string &srcp) const
#define STR(s)
Macro which performs a lexical_cast to a string.
void RecursiveReplaceTreeNode(tree_nodeRef &tn, const tree_nodeRef old_node, const tree_nodeRef &new_node, const tree_nodeRef &stmt, bool definition)
Replace the occurrences of tree node old_node with new_node in statement identified by tn...
Auxiliary methods for manipulating string.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
static const uint32_t k[]
Definition: sha-256.c:22
const unsigned int index
Represent the index read from the raw file and the index-1 of the vector of tree_node associated to t...
Definition: tree_node.hpp:146
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
This struct specifies the block node.
Definition: tree_node.hpp:1820
This file collects some utility functions.
const unsigned int function_id
The index of the function to be analyzed.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
tree_nodeRef CreateNopExpr(const tree_nodeConstRef &operand, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, unsigned int function_decl_nid) const
Create a nop_expr to perform a conversion.
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
const CustomUnorderedSet< std::pair< FrontendFlowStepType, FunctionRelationship > > ComputeFrontendRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
this class is used to manage the command-line or XML options.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
Definition: tree_node.hpp:212
Wrapper to call graph.
int debug_level
The debug level.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
DesignFlowStep_Status InternalExec() override
Computes the operations CFG graph data structure.
static tree_nodeConstRef GetFunctionReturnType(const tree_nodeConstRef &function, bool void_as_null=true)
Return the return type of a function.
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
int sl
Definition: adpcm.c:105
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:52 for PandA-2024.02 by doxygen 1.8.13