PandA-2024.02
var_computation.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  */
45 #include "var_computation.hpp"
47 
49 #include "application_manager.hpp"
50 #include "behavioral_helper.hpp"
51 #include "function_behavior.hpp"
52 #include "graph.hpp"
53 #include "op_graph.hpp"
55 
57 #include "Parameter.hpp"
58 
60 #include <fstream>
61 
63 #include "ext_tree_node.hpp"
64 #include "tree_helper.hpp"
65 #include "tree_node.hpp"
66 #include "tree_reindex.hpp"
67 
69 #include "dbgPrintHelper.hpp"
70 #include "exceptions.hpp"
71 
73 #include "compiler_wrapper.hpp"
74 #include "string_manipulation.hpp" // for GET_CLASS
75 
76 #define TOSTRING(id) std::to_string(id)
77 
79  unsigned int _function_id, const DesignFlowManagerConstRef _design_flow_manager)
80  : FunctionFrontendFlowStep(_AppM, _function_id, VAR_ANALYSIS, _design_flow_manager, _parameters),
81  ogc(function_behavior->ogc),
82  cfg(function_behavior->CGetOpGraph(FunctionBehavior::CFG)),
83  behavioral_helper(function_behavior->GetBehavioralHelper())
84 {
85  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
86 }
87 
89 
92 {
94  switch(relationship_type)
95  {
97  {
98  relationships.insert(std::make_pair(OPERATIONS_CFG_COMPUTATION, SAME_FUNCTION));
99  break;
100  }
102  {
103  break;
104  }
106  {
107  relationships.insert(std::make_pair(BUILD_VIRTUAL_PHI, SAME_FUNCTION));
108  break;
109  }
110  default:
111  {
112  THROW_UNREACHABLE("");
113  }
114  }
115  return relationships;
116 }
117 
119 {
120  if(bb_version != 0 && bb_version != function_behavior->GetBBVersion())
121  {
122  const OpGraphRef mod_cfg = function_behavior->GetOpGraph(FunctionBehavior::CFG);
123  if(boost::num_vertices(*mod_cfg) != 0)
124  {
125  VertexIterator op, op_end;
126  for(boost::tie(op, op_end) = boost::vertices(*mod_cfg); op != op_end; op++)
127  {
128  const OpNodeInfoRef op_node_info = mod_cfg->GetOpNodeInfo(*op);
129  op_node_info->cited_variables.clear();
130  op_node_info->variables.clear();
131  op_node_info->actual_parameters.clear();
132  op_node_info->Initialize();
133  }
134  }
135  }
136 }
137 
139 {
140  VertexIterator VerIt, VerItEnd;
141  std::list<vertex> Vertices;
142  for(boost::tie(VerIt, VerItEnd) = boost::vertices(*cfg); VerIt != VerItEnd; VerIt++)
143  {
144  Vertices.push_back(*VerIt);
145  }
146  std::list<vertex> PhiNodes;
147  for(auto Ver = Vertices.begin(); Ver != Vertices.end();)
148  {
149  auto curr_Ver = Ver;
150  ++Ver;
151  if(GET_TYPE(cfg, *curr_Ver) == TYPE_VPHI)
152  {
153  PhiNodes.push_back(*curr_Ver);
154  Vertices.erase(curr_Ver);
155  }
156  }
157  for(const auto& Ver : Vertices)
158  {
159  const auto& node = cfg->CGetOpNodeInfo(Ver)->node;
160  if(node)
161  {
163  }
164  }
165  for(const auto& PhiNode : PhiNodes)
166  {
167  const auto& node = cfg->CGetOpNodeInfo(PhiNode)->node;
168  if(node)
169  {
171  }
172  }
173  if(parameters->getOption<bool>(OPT_print_dot))
174  {
175  function_behavior->CGetOpGraph(FunctionBehavior::CFG)->WriteDot("OP_Variables.dot", 1);
176  }
178 }
179 
180 void VarComputation::RecursivelyAnalyze(const vertex op_vertex, const tree_nodeConstRef& _tree_node,
181  const FunctionBehavior_VariableAccessType access_type) const
182 {
183  const auto tree_node = GET_CONST_NODE(_tree_node);
184  const auto node_kind = tree_node->get_kind();
186  "-->Analyzing node " + STR(tree_node) + "(" + tree_node::GetString(node_kind) + ")");
187 
188  const auto gn = GetPointer<const gimple_node>(tree_node);
189 
190  if(GetPointer<const gimple_node>(tree_node) && (gn->vuses.size() || gn->vdef))
191  {
192  AnalyzeVops(op_vertex, GetPointer<const gimple_node>(tree_node));
193  }
194 
195  switch(node_kind)
196  {
197  case gimple_nop_K:
198  case gimple_pragma_K:
199  break;
200  case gimple_assign_K:
201  {
202  const auto* ga = GetPointerS<const gimple_assign>(tree_node);
205  if(ga->predicate)
206  {
208  }
209  break;
210  }
211  case gimple_phi_K:
212  {
213  const auto* pn = GetPointerS<const gimple_phi>(tree_node);
214  for(const auto& def_edge : pn->CGetDefEdgesList())
215  {
217  }
219  break;
220  }
221  case gimple_return_K:
222  {
223  const auto* gr = GetPointerS<const gimple_return>(tree_node);
224  const auto& op = gr->op;
225  if(op)
226  {
228  }
229  break;
230  }
231  case aggr_init_expr_K:
232  case call_expr_K:
233  {
234  const auto* ce = GetPointerS<const call_expr>(tree_node);
236  if(GET_CONST_NODE(ce->fn)->get_kind() == ssa_name_K)
237  {
239  }
240  for(const auto& arg : ce->args)
241  {
243  ogc->add_parameter(op_vertex, arg->index);
245  }
246  break;
247  }
248  case gimple_call_K:
249  {
250  const auto* gc = GetPointer<const gimple_call>(tree_node);
252  if(GET_CONST_NODE(gc->fn)->get_kind() == ssa_name_K)
253  {
255  }
256  for(const auto& arg : gc->args)
257  {
259  ogc->add_parameter(op_vertex, arg->index);
261  }
262 
263  break;
264  }
265  case gimple_cond_K:
266  {
267  RecursivelyAnalyze(op_vertex, GetPointerS<const gimple_cond>(tree_node)->op0,
269  break;
270  }
271  case gimple_while_K:
272  {
273  RecursivelyAnalyze(op_vertex, GetPointerS<const gimple_while>(tree_node)->op0,
275  break;
276  }
277  case gimple_for_K:
278  {
279  const auto* fe = GetPointerS<const gimple_for>(tree_node);
283  break;
284  }
285  case gimple_multi_way_if_K:
286  {
287  const auto* gmwi = GetPointerS<const gimple_multi_way_if>(tree_node);
288  for(const auto& cond : gmwi->list_of_cond)
289  {
290  if(cond.first)
291  {
293  }
294  }
295  break;
296  }
297  case gimple_switch_K:
298  {
299  const auto* gs = GetPointerS<const gimple_switch>(tree_node);
301  if(gs->op1)
302  {
304  }
305  break;
306  }
307  case gimple_label_K:
308  {
309  RecursivelyAnalyze(op_vertex, GetPointerS<const gimple_label>(tree_node)->op,
311  break;
312  }
313  case gimple_goto_K:
314  {
315  RecursivelyAnalyze(op_vertex, GetPointerS<const gimple_goto>(tree_node)->op,
317  break;
318  }
319  case gimple_asm_K:
320  {
321  const auto* asme = GetPointerS<const gimple_asm>(tree_node);
322  if(asme->out)
323  {
325  }
326  if(asme->in)
327  {
329  }
330  if(asme->clob)
331  {
333  }
334  break;
335  }
336  case function_decl_K:
337  {
338  break;
339  }
340  case var_decl_K:
341  {
342  ogc->AddSourceCodeVariable(op_vertex, tree_node->index);
343  const auto* vd = GetPointer<const var_decl>(tree_node);
344  if(vd && (!vd->scpe || GET_CONST_NODE(vd->scpe)->get_kind() == translation_unit_decl_K))
345  {
346  AppM->AddGlobalVariable(_tree_node);
347  }
348  break;
349  }
350  case parm_decl_K:
351  {
353  access_type);
354  ogc->AddSourceCodeVariable(op_vertex, tree_node->index);
355  break;
356  }
357  case result_decl_K:
358  {
359  ogc->AddSourceCodeVariable(op_vertex, tree_node->index);
360  break;
361  }
362  case ssa_name_K:
363  {
364  const auto* sn = GetPointer<const ssa_name>(tree_node);
365  if(sn->virtual_flag)
366  {
367  switch(access_type)
368  {
371  ogc->AddVariable(op_vertex, tree_node->index, FunctionBehavior_VariableType::VIRTUAL, access_type);
372  break;
374  ogc->AddVariable(op_vertex, tree_node->index, FunctionBehavior_VariableType::VIRTUAL,
376  break;
379  THROW_UNREACHABLE("Address expresion of a virtual variable");
380  break;
382  default:
383  THROW_UNREACHABLE("");
384  }
385  }
386  else
387  {
388  if((sn->volatile_flag ||
389  (sn->CGetDefStmts().size() == 1 && GET_CONST_NODE(sn->CGetDefStmt())->get_kind() == gimple_nop_K)) &&
390  sn->var)
391  {
393  "---Adding " + sn->ToString() + " to defs of Entry");
394  ogc->AddVariable(cfg->CGetOpGraphInfo()->entry_vertex, tree_node->index,
396  }
397  ogc->AddSourceCodeVariable(op_vertex, tree_node->index);
398  switch(access_type)
399  {
402  ogc->AddVariable(op_vertex, tree_node->index, FunctionBehavior_VariableType::SCALAR, access_type);
403  break;
405  ogc->AddVariable(op_vertex, tree_node->index, FunctionBehavior_VariableType::SCALAR,
407  break;
409  break;
411  {
412  ogc->AddVariable(op_vertex, tree_node->index, FunctionBehavior_VariableType::SCALAR,
414  ogc->AddVariable(op_vertex, tree_node->index, FunctionBehavior_VariableType::SCALAR,
416  break;
417  }
419  default:
420  THROW_UNREACHABLE("");
421  }
422  }
423  break;
424  }
425  case tree_list_K:
426  {
427  const auto* tl = GetPointerS<const tree_list>(tree_node);
428  if(tl->purp)
429  {
431  }
432  auto current_args = tree_node;
433  while(current_args)
434  {
435  const auto* current_tree_list = GetPointerS<const tree_list>(current_args);
436  RecursivelyAnalyze(op_vertex, current_tree_list->valu, access_type);
437  if(current_tree_list->chan)
438  {
439  current_args = GET_CONST_NODE(current_tree_list->chan);
440  }
441  else
442  {
443  break;
444  }
445  }
446  break;
447  }
448  case tree_vec_K:
449  {
450  const auto* tv = GetPointerS<const tree_vec>(tree_node);
451  for(const auto& op : tv->list_of_op)
452  {
453  RecursivelyAnalyze(op_vertex, op, access_type);
454  }
455  break;
456  }
458  {
459  const auto* ue = GetPointerS<const unary_expr>(tree_node);
460  if(ue->get_kind() == addr_expr_K)
461  {
463  }
464  else
465  {
467  }
468  break;
469  }
471  {
472  const auto* be = GetPointerS<const binary_expr>(tree_node);
473  if(be->get_kind() == postincrement_expr_K || be->get_kind() == postdecrement_expr_K)
474  {
477  }
480  break;
481  }
483  {
484  const auto* te = GetPointerS<const ternary_expr>(tree_node);
485 
486  if(te->get_kind() == component_ref_K || te->get_kind() == bit_field_ref_K)
487  {
488  RecursivelyAnalyze(op_vertex, te->op0, access_type);
489  }
490  else
491  {
493  }
495  if(te->op2)
496  {
498  }
499  break;
500  }
502  {
503  const auto* qe = GetPointerS<const quaternary_expr>(tree_node);
504  if((qe->get_kind() == array_ref_K || qe->get_kind() == array_range_ref_K) &&
505  GET_CONST_NODE(tree_helper::CGetType(qe->op0))->get_kind() == array_type_K)
506  {
507  RecursivelyAnalyze(op_vertex, qe->op0, access_type);
508  }
509  else
510  {
512  }
514  if(qe->op2)
515  {
517  }
518  if(qe->op3)
519  {
521  }
522  break;
523  }
524  case lut_expr_K:
525  {
526  auto* le = GetPointerS<const lut_expr>(tree_node);
529  if(le->op2)
530  {
532  }
533  if(le->op3)
534  {
536  }
537  if(le->op4)
538  {
540  }
541  if(le->op5)
542  {
544  }
545  if(le->op6)
546  {
548  }
549  if(le->op7)
550  {
552  }
553  if(le->op8)
554  {
556  }
557  break;
558  }
559  case target_mem_ref_K:
560  {
561  const auto* tm = GetPointerS<const target_mem_ref>(tree_node);
562  if(tm->symbol)
563  {
564  RecursivelyAnalyze(op_vertex, tm->symbol, access_type);
565  }
566  if(tm->base)
567  {
569  }
570  if(tm->idx)
571  {
573  }
574  break;
575  }
576  case target_mem_ref461_K:
577  {
578  const auto* tm = GetPointerS<const target_mem_ref461>(tree_node);
579  if(tm->base)
580  {
582  }
583  if(tm->idx)
584  {
586  }
587  if(tm->idx2)
588  {
590  }
591  break;
592  }
593  case constructor_K:
594  {
595  const auto* constr = GetPointerS<const constructor>(tree_node);
596  for(const auto& valu : constr->list_of_idx_valu)
597  {
599  }
600  break;
601  }
602  case case_label_expr_K:
603  {
604  const auto* cle = GetPointerS<const case_label_expr>(tree_node);
605  if(cle->op0)
606  {
608  }
609  if(cle->op1)
610  {
612  }
613  break;
614  }
615  case complex_cst_K:
616  case const_decl_K:
617  case field_decl_K:
618  case integer_cst_K:
619  case label_decl_K:
620  case namespace_decl_K:
621  case template_decl_K:
622  case real_cst_K:
623  case string_cst_K:
624  case vector_cst_K:
625  case void_cst_K:
626  {
627  break;
628  }
629  case binfo_K:
630  case block_K:
631  case gimple_bind_K:
632  case gimple_predict_K:
633  case gimple_resx_K:
634  case identifier_node_K:
635  case translation_unit_decl_K:
636  case error_mark_K:
637  case using_decl_K:
638  case type_decl_K:
639  case CASE_CPP_NODES:
640  case CASE_FAKE_NODES:
641  case issue_pragma_K:
642  case blackbox_pragma_K:
643  case profiling_pragma_K:
644  case statistical_profiling_K:
645  case map_pragma_K:
646  case call_hw_pragma_K:
647  case call_point_hw_pragma_K:
648  case omp_pragma_K:
649  case null_node_K:
650  case omp_atomic_pragma_K:
651  case omp_critical_pragma_K:
652  case omp_declare_simd_pragma_K:
653  case omp_for_pragma_K:
654  case omp_parallel_pragma_K:
655  case omp_sections_pragma_K:
656  case omp_simd_pragma_K:
657  case omp_parallel_sections_pragma_K:
658  case omp_section_pragma_K:
659  case omp_task_pragma_K:
660  case omp_target_pragma_K:
661  case statement_list_K:
662  case CASE_TYPE_NODES:
663  case target_expr_K:
664  {
665  THROW_UNREACHABLE("Unexpected tree node: " + tree_node::GetString(node_kind));
666  break;
667  }
668  default:
669  {
670  THROW_UNREACHABLE("");
671  }
672  }
674  "<--Analyzed node " + STR(tree_node) + "(" + tree_node::GetString(node_kind) + ")");
675  return;
676 }
677 
678 void VarComputation::AnalyzeVops(const vertex op_vertex, const gimple_node* vop) const
679 {
680  for(const auto& vuse : vop->vuses)
681  {
682  ogc->AddVariable(op_vertex, GET_INDEX_NODE(vuse), FunctionBehavior_VariableType::VIRTUAL,
684  }
685  if(vop->vdef)
686  {
687  ogc->AddVariable(op_vertex, GET_INDEX_NODE(vop->vdef), FunctionBehavior_VariableType::VIRTUAL,
689  }
690  for(auto const& vover : vop->vovers)
691  {
692  ogc->AddVariable(op_vertex, GET_INDEX_NODE(vover), FunctionBehavior_VariableType::VIRTUAL,
694  }
695 }
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
Analyzes operations and creates the sets of read and written variables.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
DesignFlowStep_Status InternalExec() override
Computes the set of read and written variables.
#define GET_TYPE(data, vertex_index)
Helper macro returning the type associated with a node.
File containing functions and utilities to support the printing of debug messagges.
#define CASE_BINARY_EXPRESSION
This macro collects all case labels for binary_expr objects.
Definition: tree_node.hpp:463
#define TYPE_VPHI
constant string identifying an operation node of type virtual phi-nodes
Definition: op_graph.hpp:162
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
void RecursivelyAnalyze(const vertex op_vertex, const tree_nodeConstRef &tree_node, const FunctionBehavior_VariableAccessType access_type) const
Recursively analyze a tree_node.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
static std::string GetString(const enum kind k)
Given a kind, return the corresponding string.
Definition: tree_node.cpp:120
Class specification of the graph structures.
exceptions managed by PandA
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.
#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
unsigned int bb_version
The version of the basic block intermediate representation on which this step has been applied...
Abstract pure class for the tree structure.
Definition: tree_node.hpp:139
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.
const OpGraphConstRef cfg
The control flow graph of the function.
const OpNodeInfoConstRef CGetOpNodeInfo(const vertex node) const
Returns the info associated with a node.
Definition: op_graph.hpp:843
TreeNodeSet vovers
vovers of this statement
Definition: tree_node.hpp:1112
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
const operations_graph_constructorRef ogc
The operation graph constructor.
#define CASE_QUATERNARY_EXPRESSION
This macro collects all case labels for quaternary_expr objects.
Definition: tree_node.hpp:574
Control flow graph.
#define CASE_UNARY_EXPRESSION
This macro collects all case labels for unary_expr objects.
Definition: tree_node.hpp:371
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
const OpGraphInfoConstRef CGetOpGraphInfo() const
Returns the property associated with the graph.
Definition: op_graph.hpp:871
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
FunctionBehavior_VariableAccessType
The access type to a variable.
boost::graph_traits< graph >::vertex_iterator VertexIterator
vertex_iterator definition.
Definition: graph.hpp:1307
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
#define DEBUG_LEVEL_NONE
no debugging print is performed.
~VarComputation() override
Destructor.
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
Definition: tree_node.hpp:581
This file collects some utility functions.
VarComputation(const ParameterConstRef _parameters, const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
#define CASE_FAKE_NODES
This macro collects all case labels for fake or empty nodes.
Definition: tree_node.hpp:635
struct definition of the common part of a gimple with virtual operands
Definition: tree_node.hpp:1078
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
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
TreeNodeSet vuses
vuses of this statement
Definition: tree_node.hpp:1102
tree_nodeRef vdef
vdef of this statement
Definition: tree_node.hpp:1093
int debug_level
The debug level.
void AnalyzeVops(const vertex op_vertex, const gimple_node *vops) const
Analyze virtual operands associated with a gimple node.
This class provides methods to build an operations graph.
#define CASE_TERNARY_EXPRESSION
This macro collects all case labels for ternary_expr objects.
Definition: tree_node.hpp:550
A brief description of the C++ Header File.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
Implementation of the wrapper to Gcc for C sources.

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