PandA-2024.02
call_graph_builtin_call.cpp
Go to the documentation of this file.
1 /*
2  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
3  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
4  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
5  * _/ _/ _/ _/ _/ _/ _/ _/ _/
6  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
7  *
8  * ***********************************************
9  * PandA Project
10  * URL: http://panda.dei.polimi.it
11  * Politecnico di Milano - DEIB
12  * System Architectures Group
13  * ***********************************************
14  * Copyright (C) 2004-2024 Politecnico di Milano
15  *
16  * This file is part of the PandA framework.
17  *
18  * The PandA framework is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program. If not, see <http://www.gnu.org/licenses/>.
30  */
31 
33 
34 #include "custom_map.hpp"
35 #include <string>
36 
37 #include "Parameter.hpp"
38 #include "application_manager.hpp"
39 #include "basic_block.hpp"
40 #include "call_graph.hpp"
41 #include "call_graph_manager.hpp"
42 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
43 #include "design_flow_manager.hpp"
44 #include "ext_tree_node.hpp"
45 #include "function_behavior.hpp"
46 #include "function_decl_refs.hpp"
47 #include "op_graph.hpp"
48 #include "string_manipulation.hpp" // for GET_CLASS
50 #include "tree_basic_block.hpp"
51 #include "tree_helper.hpp"
52 #include "tree_manager.hpp"
53 #include "tree_node.hpp"
54 #include "tree_reindex.hpp"
55 
58 {
59  THROW_ASSERT(TN->get_kind() == tree_reindex_K, "Node is not a tree reindex");
61  "-->Update recursively node: " + STR(GET_NODE(TN)) + " id: " + STR(GET_INDEX_NODE(TN)));
62 
63  const tree_managerRef TM = AppM->get_tree_manager();
64  const tree_nodeRef currentTreeNode = GET_NODE(TN);
66  switch(currentTreeNode->get_kind())
67  {
68  case call_expr_K:
69  case aggr_init_expr_K:
70  {
71  const call_expr* CE = GetPointer<call_expr>(currentTreeNode);
72 
73  tree_nodeRef FN =
74  GetPointer<addr_expr>(GET_NODE(CE->fn)) ? GetPointer<addr_expr>(GET_NODE(CE->fn))->op : CE->fn;
75  THROW_ASSERT(FN, "Address expression with null op");
76  if(GET_NODE(FN)->get_kind() == function_decl_K)
77  {
78  unsigned int functionDeclIdx = FN->index;
79  std::string funName = tree_helper::name_function(TM, functionDeclIdx);
80  if(funName == BUILTIN_WAIT_CALL)
81  {
82  const std::vector<tree_nodeRef>& args = CE->args;
83  tree_nodeRef builtinArgZero =
84  GetPointer<addr_expr>(GET_NODE(args[0])) ? GetPointer<addr_expr>(GET_NODE(args[0]))->op : args[0];
85  if(GET_NODE(builtinArgZero)->get_kind() == function_decl_K)
86  {
87  unsigned int calledFunctionId = builtinArgZero->index;
91  modified = true;
92  }
93  else if(GET_NODE(builtinArgZero)->get_kind() == ssa_name_K)
94  {
95  tree_nodeRef funPtrType = getFunctionPointerType(GET_NODE(builtinArgZero));
96  ExtendCallGraph(function_id, funPtrType, CE->index);
97  }
98  }
99  }
100  break;
101  }
102  case gimple_call_K:
103  {
104  const gimple_call* CE = GetPointer<gimple_call>(currentTreeNode);
105 
106  tree_nodeRef FN =
107  GetPointer<addr_expr>(GET_NODE(CE->fn)) ? GetPointer<addr_expr>(GET_NODE(CE->fn))->op : CE->fn;
108  THROW_ASSERT(FN, "Address expression with null op");
109  if(GET_NODE(FN)->get_kind() == function_decl_K)
110  {
111  unsigned int functionDeclIdx = GET_NODE(FN)->index;
112  std::string funName = tree_helper::name_function(TM, functionDeclIdx);
113  if(funName == BUILTIN_WAIT_CALL)
114  {
115  const std::vector<tree_nodeRef>& args = CE->args;
116  tree_nodeRef builtinArgZero =
117  GetPointer<addr_expr>(GET_NODE(args[0])) ? GetPointer<addr_expr>(GET_NODE(args[0]))->op : args[0];
118  if(GET_NODE(builtinArgZero)->get_kind() == function_decl_K)
119  {
120  unsigned int calledFunctionId = builtinArgZero->index;
124  modified = true;
125  }
126  else if(GET_NODE(builtinArgZero)->get_kind() == ssa_name_K)
127  {
128  // Function pointers case.
129  tree_nodeRef funPtrType = getFunctionPointerType(GET_NODE(builtinArgZero));
130  ExtendCallGraph(function_id, funPtrType, CE->index);
131  }
132  }
133  }
134  break;
135  }
136  case gimple_assign_K:
137  {
138  auto* gm = GetPointer<gimple_assign>(currentTreeNode);
139  if(GetPointer<call_expr>(GET_NODE(gm->op1)))
140  {
141  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---call_expr " + STR(GET_NODE(gm->op1)));
142  lookForBuiltinCall(gm->op1);
143  }
144  break;
145  }
146  case gimple_nop_K:
147  case var_decl_K:
148  case parm_decl_K:
149  case ssa_name_K:
150  case tree_list_K:
155  case lut_expr_K:
156  case constructor_K:
157  case gimple_cond_K:
158  case gimple_switch_K:
159  case gimple_multi_way_if_K:
160  case gimple_return_K:
161  case gimple_for_K:
162  case gimple_while_K:
163  case CASE_TYPE_NODES:
164  case type_decl_K:
165  case target_expr_K:
166  case target_mem_ref_K:
167  case target_mem_ref461_K:
168  case real_cst_K:
169  case complex_cst_K:
170  case string_cst_K:
171  case integer_cst_K:
172  case field_decl_K:
173  case function_decl_K:
174  case label_decl_K:
175  case result_decl_K:
176  case vector_cst_K:
177  case void_cst_K:
178  case tree_vec_K:
179  case case_label_expr_K:
180  case gimple_label_K:
181  case gimple_asm_K:
182  case gimple_goto_K:
183  case CASE_PRAGMA_NODES:
184  case binfo_K:
185  case block_K:
186  case const_decl_K:
187  case CASE_CPP_NODES:
188  case gimple_bind_K:
189  case gimple_phi_K:
190  case gimple_pragma_K:
191  case gimple_predict_K:
192  case gimple_resx_K:
193  case identifier_node_K:
194  case last_tree_K:
195  case namespace_decl_K:
196  case none_K:
197  case placeholder_expr_K:
198  case statement_list_K:
199  case translation_unit_decl_K:
200  case error_mark_K:
201  case using_decl_K:
202  case template_decl_K:
203  case tree_reindex_K:
204  default:
205  {
206  THROW_UNREACHABLE("");
207  }
208  }
209  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Updated recursively " + STR(GET_INDEX_NODE(TN)));
210 }
211 
212 void CallGraphBuiltinCall::ExtendCallGraph(unsigned int callerIdx, tree_nodeRef funType, unsigned int stmtIdx)
213 {
214  std::string type = tree_helper::print_type(AppM->get_tree_manager(), funType->index);
216  for(unsigned int Itr : typeToDeclaration[type])
217  {
220  modified = true;
221  }
222 }
223 
226 {
228  switch(RT)
229  {
231  {
232  relationships.insert(std::make_pair(HWCALL_INJECTION, SAME_FUNCTION));
233  relationships.insert(std::make_pair(FUNCTION_ANALYSIS, WHOLE_APPLICATION));
234  break;
235  }
238  {
239  break;
240  }
241  default:
242  THROW_UNREACHABLE("HWCallInjection::ComputeFrontendRelationships");
243  }
244  return relationships;
245 }
246 
248  const DesignFlowManagerConstRef DFM, const ParameterConstRef P)
249  : FunctionFrontendFlowStep(AM, functionId, CALL_GRAPH_BUILTIN_CALL, DFM, P),
250  modified(false),
252 {
253  debug_level = P->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
254 }
255 
257 
259 {
260 }
261 
263 {
265  {
266  tree_managerRef TM = AppM->get_tree_manager();
267  const CallGraphManagerRef CGM = AppM->GetCallGraphManager();
268  const auto root_functions = CGM->GetRootFunctions();
270  function_decl_refs fdr_visitor(allFunctions);
271  for(const auto root_function : root_functions)
272  {
273  tree_nodeRef rf = TM->get_tree_node_const(root_function);
274  rf->visit(&fdr_visitor);
275  }
276  for(unsigned int allFunction : allFunctions)
277  {
278  std::string functionName = tree_helper::name_function(TM, allFunction);
280  "---Analyzing function " + STR(allFunction) + " " + functionName);
281  tree_nodeRef function = TM->get_tree_node_const(allFunction);
282  auto* funDecl = GetPointer<function_decl>(function);
283  std::string type = tree_helper::print_type(TM, GET_INDEX_NODE(funDecl->type));
284  if(funDecl->body && functionName != "__start_pragma__" && functionName != "__close_pragma__" &&
285  !starts_with(functionName, "__pragma__"))
286  {
287  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---FunctionTypeString " + type);
288  }
289  typeToDeclaration[type].insert(allFunction);
290  }
291  typeToDeclarationBuilt = true;
292  }
293 }
294 
296 {
297  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->BuiltinWaitCall Analysis");
298  tree_managerRef TM = AppM->get_tree_manager();
299  const tree_nodeRef currentTreeNode = TM->GetTreeNode(function_id);
300  auto* functionDecl = GetPointer<function_decl>(currentTreeNode);
301  auto* stmtList = GetPointer<statement_list>(GET_NODE(functionDecl->body));
302 
303  if(parameters->getOption<bool>(OPT_print_dot) && DEBUG_LEVEL_PEDANTIC <= debug_level &&
304  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
305  {
306  AppM->CGetCallGraphManager()->CGetCallGraph()->WriteDot("builtin-graph-pre" + STR(function_id) + ".dot");
307  }
308  already_visited.clear();
309  modified = false;
310  typeToDeclaration.clear();
311  typeToDeclarationBuilt = false;
312 
313  for(const auto& block : stmtList->list_of_bloc)
314  {
315  for(const auto& stmt : block.second->CGetStmtList())
316  {
317  if(GET_NODE(stmt)->get_kind() == gimple_call_K or GET_NODE(stmt)->get_kind() == gimple_assign_K)
318  {
319  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Analyzing stmt " + stmt->ToString());
320  lookForBuiltinCall(stmt);
321  }
322  }
323  }
324 
325  if(parameters->getOption<bool>(OPT_print_dot) && DEBUG_LEVEL_PEDANTIC <= debug_level &&
326  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
327  {
328  AppM->CGetCallGraphManager()->CGetCallGraph()->WriteDot("builtin-graph-post" + STR(function_id) + ".dot");
329  }
330 
331  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--BuiltinWaitCall Analysis completed");
332  modified ? function_behavior->UpdateBBVersion() : 0;
334 }
335 
337 {
338  auto* sa = GetPointer<ssa_name>(fptr);
339  THROW_ASSERT(sa, "Function pointer not in SSA-form");
340  pointer_type* pt;
341  if(sa->var)
342  {
343  auto* var = GetPointer<decl_node>(GET_NODE(sa->var));
344  THROW_ASSERT(var, "Call expression does not point to a declaration node");
345  pt = GetPointer<pointer_type>(GET_NODE(var->type));
346  }
347  else
348  {
349  pt = GetPointer<pointer_type>(GET_NODE(sa->type));
350  }
351 
352  THROW_ASSERT(pt, "Declaration node has not information about pointer_type");
353  THROW_ASSERT(GetPointer<function_type>(GET_NODE(pt->ptd)),
354  "Pointer type has not information about pointed function_type");
355 
356  return GET_NODE(pt->ptd);
357 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
TypeDeclarationMap typeToDeclaration
Map function types to matching declarations.
tree_nodeRef ptd
ptd field points to the node for the type pointed to.
Definition: tree_node.hpp:3909
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
CallGraphBuiltinCall(const application_managerRef AM, unsigned int functionId, const DesignFlowManagerConstRef DFM, const ParameterConstRef P)
Ctor.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
static std::string name_function(const tree_managerConstRef &tm, const unsigned int index)
Return the name of the function.
File containing functions and utilities to support the printing of debug messagges.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
Step successfully executed.
#define CASE_BINARY_EXPRESSION
This macro collects all case labels for binary_expr objects.
Definition: tree_node.hpp:463
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
static std::string print_type(const tree_managerConstRef &TM, unsigned int type, bool global=false, bool print_qualifiers=false, bool print_storage=false, unsigned int var=0, const var_pp_functorConstRef &vppf=var_pp_functorConstRef(), const std::string &prefix="", const std::string &tail="")
Print a type and its variable in case var is not zero.
const CustomUnorderedSet< std::pair< FrontendFlowStepType, FunctionRelationship > > ComputeFrontendRelationships(DesignFlowStep::RelationshipType RT) const override
State relationship with other design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
virtual void visit(tree_node_visitor *const v) const
virtual function used to traverse the tree_node data structure.
#define BUILTIN_WAIT_CALL
constant defining the builtin wait call intrinsic function
Definition: op_graph.hpp:358
#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
std::vector< tree_nodeRef > args
The arguments of the gimple_call.
Definition: tree_node.hpp:1968
Data structure describing a basic block at tree level.
redefinition of map to manage ordered/unordered structures
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
std::vector< tree_nodeRef > args
The arguments of the call_expr.
Definition: tree_node.hpp:1882
static void addCallPointAndExpand(CustomUnorderedSet< unsigned int > &AV, const application_managerRef AM, unsigned int caller_id, unsigned int called_id, unsigned int call_id, enum FunctionEdgeInfo::CallType call_type, int DL)
const tree_nodeRef get_tree_node_const(unsigned int i) const
Return the reference to the i-th tree_node Constant version of get_tree_node.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
virtual std::string get_kind_text() const =0
Virtual function returning the name of the actual class.
bool starts_with(const std::string &str, const std::string &pattern)
const size_t P
Definition: helm.c:5
#define CASE_QUATERNARY_EXPRESSION
This macro collects all case labels for quaternary_expr objects.
Definition: tree_node.hpp:574
#define CASE_UNARY_EXPRESSION
This macro collects all case labels for unary_expr objects.
Definition: tree_node.hpp:371
void lookForBuiltinCall(const tree_nodeRef TN)
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
static tree_nodeRef getFunctionPointerType(tree_nodeRef fptr)
tree_nodeRef fn
fn is the operand 0 of the call expression: this is the function
Definition: tree_node.hpp:1879
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Call graph hierarchy.
#define DEBUG_LEVEL_NONE
no debugging print is performed.
Wrapper of design_flow.
struct definition of the pointer_type tree node.
Definition: tree_node.hpp:3896
This struct specifies the block node.
Definition: tree_node.hpp:1820
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
Definition: tree_node.hpp:581
This file collects some utility functions.
tree_nodeRef GetTreeNode(const unsigned int index) const
Return the index-th tree_node (modifiable version)
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.
This struct specifies the call_expr node.
Definition: tree_node.hpp:1873
Class specification of the basic_block structure.
Data structures used in operations graph.
~CallGraphBuiltinCall() override
Classes specification of the tree_node data structures not present in the gcc.
this class is used to manage the command-line or XML options.
#define CASE_CPP_NODES
This macro collects all case labels for cpp nodes.
Definition: tree_node.hpp:644
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
Wrapper to call graph.
int debug_level
The debug level.
tree node visitor collecting the function_decl referred by starting from a given node ...
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
DesignFlowStep_Status InternalExec() override
Execute the step.
This file contains the declaration of the CallGraphBuiltinCall pass that will add function called thr...
This class models the application of a analysis to all the functions of an application.
This struct specifies the gimple_call node.
Definition: tree_node.hpp:1959
CustomUnorderedSet< unsigned int > already_visited
Already visited tree node (used to avoid infinite recursion)
#define CASE_TERNARY_EXPRESSION
This macro collects all case labels for ternary_expr objects.
Definition: tree_node.hpp:550
Class specification of the manager of the tree structures extracted from the raw file.
void ExtendCallGraph(unsigned int callerIdx, tree_nodeRef funType, unsigned int stmtIdx)
A brief description of the C++ Header File.
tree_nodeRef fn
fn is the operand 0 of the call expression: this is the function
Definition: tree_node.hpp:1965
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
Definition: tree_node.hpp:610
#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:51 for PandA-2024.02 by doxygen 1.8.13