PandA-2024.02
determine_memory_accesses.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  */
47 #include "config_HAVE_PRAGMA_BUILT.hpp"
48 
50 #include "application_manager.hpp"
51 #include "call_graph.hpp"
52 #include "call_graph_manager.hpp"
53 #include "function_behavior.hpp"
54 
56 #include "Parameter.hpp"
57 #include "module_interface.hpp"
58 
60 #include "behavioral_helper.hpp"
61 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
62 #include "ext_tree_node.hpp"
63 #include "op_graph.hpp"
64 #include "string_manipulation.hpp" // for GET_CLASS
65 #include "tree_basic_block.hpp"
66 #include "tree_helper.hpp"
67 #include "tree_manager.hpp"
68 #include "tree_node.hpp"
69 #include "tree_reindex.hpp"
70 
72  const application_managerRef _AppM, unsigned int _function_id,
73  const DesignFlowManagerConstRef _design_flow_manager)
74  : FunctionFrontendFlowStep(_AppM, _function_id, DETERMINE_MEMORY_ACCESSES, _design_flow_manager, _parameters),
75  behavioral_helper(function_behavior->CGetBehavioralHelper()),
76  TM(_AppM->get_tree_manager())
77 {
78  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
79 }
80 
82 
85 {
87  switch(relationship_type)
88  {
90  {
91  if(parameters->isOption(OPT_writer_language))
92  {
93  relationships.insert(std::make_pair(HDL_VAR_DECL_FIX, SAME_FUNCTION));
94  }
95  else
96  {
97  relationships.insert(std::make_pair(VAR_DECL_FIX, SAME_FUNCTION));
98  }
99  relationships.insert(std::make_pair(CALL_GRAPH_BUILTIN_CALL, SAME_FUNCTION));
100  relationships.insert(std::make_pair(DETERMINE_MEMORY_ACCESSES, CALLED_FUNCTIONS));
101  relationships.insert(std::make_pair(FIX_STRUCTS_PASSED_BY_VALUE, SAME_FUNCTION));
102  relationships.insert(std::make_pair(FUNCTION_CALL_TYPE_CLEANUP, SAME_FUNCTION));
103  relationships.insert(std::make_pair(IR_LOWERING, SAME_FUNCTION));
104  relationships.insert(std::make_pair(PARM_DECL_TAKEN_ADDRESS, SAME_FUNCTION));
105  relationships.insert(std::make_pair(PARM2SSA, SAME_FUNCTION));
106  relationships.insert(std::make_pair(REBUILD_INITIALIZATION, SAME_FUNCTION));
107  relationships.insert(std::make_pair(REBUILD_INITIALIZATION2, SAME_FUNCTION));
108  relationships.insert(std::make_pair(UN_COMPARISON_LOWERING, SAME_FUNCTION));
109  break;
110  }
112  {
113  break;
114  }
116  {
117  break;
118  }
119  default:
120  {
121  THROW_UNREACHABLE("");
122  }
123  }
124  return relationships;
125 }
126 
128 {
129  const auto tn = TM->CGetTreeNode(function_id);
130  const auto fd = GetPointer<const function_decl>(tn);
131  if(!fd || !fd->body)
132  {
133  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Node is not a function or it hasn't a body");
135  }
136  const CustomOrderedSet<unsigned int> before_function_mem = function_behavior->get_function_mem();
137  const bool before_has_globals = function_behavior->get_has_globals();
138  const CustomOrderedSet<unsigned int> before_state_variables = function_behavior->get_state_variables();
139  const CustomOrderedSet<unsigned int> before_dynamic_address = function_behavior->get_dynamic_address();
140  const CustomOrderedSet<unsigned int> before_parm_decl_copied = function_behavior->get_parm_decl_copied();
141  const CustomOrderedSet<unsigned int> before_parm_decl_loaded = function_behavior->get_parm_decl_loaded();
142  const CustomOrderedSet<unsigned int> before_parm_decl_stored = function_behavior->get_parm_decl_stored();
143  const bool before_dereference_unknown_addr = function_behavior->get_dereference_unknown_addr();
144  const bool before_has_undefined_function_receiving_pointers =
145  function_behavior->get_has_undefined_function_receiving_pointers();
146 
148  function_behavior->clean_function_mem();
149  function_behavior->set_has_globals(false);
150  function_behavior->clean_state_variable();
151  function_behavior->clean_dynamic_address();
152  function_behavior->clean_parm_decl_copied();
153  function_behavior->clean_parm_decl_loaded();
154  function_behavior->clean_parm_decl_stored();
155  function_behavior->set_dereference_unknown_addr(false);
156  function_behavior->set_has_undefined_function_receiveing_pointers(false);
157 
159  for(const auto& formal : fd->list_of_args)
160  {
161  analyze_node(formal, false, false, false);
162  }
163 
164  const auto sl = GetPointer<const statement_list>(GET_CONST_NODE(fd->body));
165  THROW_ASSERT(sl, "Body is not a statement_list");
166  for(const auto& bb : sl->list_of_bloc)
167  {
168  if(bb.second->number == BB_ENTRY || bb.second->number == BB_EXIT)
169  {
170  continue;
171  }
172  for(const auto& phi : bb.second->CGetPhiList())
173  {
174  analyze_node(phi, false, false, false);
175  }
176  for(const auto& stmt : bb.second->CGetStmtList())
177  {
178  analyze_node(stmt, false, false, false);
179  }
180  }
181 
182  if(debug_level >= DEBUG_LEVEL_PEDANTIC && parameters->getOption<bool>(OPT_print_dot))
183  {
184  AppM->CGetCallGraphManager()->CGetCallGraph()->WriteDot("call_graph_memory_analysis.dot");
185  }
187  already_visited_ae.clear();
188  already_visited.clear();
189 
190  bool changed = before_function_mem != function_behavior->get_function_mem() ||
191  before_has_globals != function_behavior->get_has_globals() ||
192  before_state_variables != function_behavior->get_state_variables() ||
193  before_dynamic_address != function_behavior->get_dynamic_address() ||
194  before_parm_decl_copied != function_behavior->get_parm_decl_copied() ||
195  before_parm_decl_loaded != function_behavior->get_parm_decl_loaded() ||
196  before_parm_decl_stored != function_behavior->get_parm_decl_stored() ||
197  before_dereference_unknown_addr != function_behavior->get_dereference_unknown_addr() ||
198  before_has_undefined_function_receiving_pointers !=
199  function_behavior->get_has_undefined_function_receiving_pointers();
201 }
202 
203 void determine_memory_accesses::analyze_node(const tree_nodeConstRef& _tn, bool left_p, bool dynamic_address,
204  bool no_dynamic_address)
205 {
206  const auto tn = _tn->get_kind() == tree_reindex_K ? GET_CONST_NODE(_tn) : _tn;
207  const auto node_id = tn->index;
208  const auto tn_kind = tn->get_kind();
209  if(tn_kind != addr_expr_K && tn_kind != var_decl_K)
210  {
211  if(already_visited.find(node_id) != already_visited.end())
212  {
213  return;
214  }
215  else
216  {
217  already_visited.insert(node_id);
218  }
219  }
221  "-->Analyzing node " + tn->ToString() +
222  " - Dynamic address: " + (dynamic_address ? " true" : "false") +
223  " - No dynamic address: " + (no_dynamic_address ? "true" : "false"));
224  std::string function_name = behavioral_helper->get_function_name();
225 
226  const auto gn = GetPointer<const gimple_node>(tn);
227  if(gn && gn->use_set)
228  {
229  for(const auto& usv : gn->use_set->variables)
230  {
231  analyze_node(usv, false, true, false);
232  }
233  }
234 
235  switch(tn_kind)
236  {
237  case gimple_assign_K:
238  {
239  const auto gm = GetPointerS<const gimple_assign>(tn);
240  if(!gm->init_assignment)
241  {
242  // std::cerr << "gimple assign " << node_id << " " << tn << std::endl;
243  analyze_node(gm->op0, true, false, false);
244  analyze_node(gm->op1, false, false, gm->temporary_address);
245 
247  const auto op0 = GET_CONST_NODE(gm->op0);
248  const auto op1 = GET_CONST_NODE(gm->op1);
249  const auto op0_kind = op0->get_kind();
250  const auto op1_kind = op1->get_kind();
251  const auto op0_type = tree_helper::CGetType(op0);
252  const auto op1_type = tree_helper::CGetType(op1);
253 
254  bool is_a_vector_bitfield = false;
255  if(op1_kind == bit_field_ref_K)
256  {
257  const auto bfr = GetPointerS<const bit_field_ref>(op1);
258  if(tree_helper::IsVectorType(bfr->op0))
259  {
260  is_a_vector_bitfield = true;
261  }
262  }
263 
264  auto load_candidate =
265  (op1_kind == bit_field_ref_K && !is_a_vector_bitfield) || op1_kind == component_ref_K ||
266  op1_kind == indirect_ref_K || op1_kind == misaligned_indirect_ref_K || op1_kind == mem_ref_K ||
267  op1_kind == array_ref_K || op1_kind == target_mem_ref_K || op1_kind == target_mem_ref461_K;
268  if(op1_kind == realpart_expr_K || op1_kind == imagpart_expr_K)
269  {
270  const auto code1 = GET_CONST_NODE(GetPointerS<const unary_expr>(op1)->op)->get_kind();
271  if((code1 == bit_field_ref_K && !is_a_vector_bitfield) || code1 == component_ref_K ||
272  code1 == indirect_ref_K || code1 == bit_field_ref_K || code1 == misaligned_indirect_ref_K ||
273  code1 == mem_ref_K || code1 == array_ref_K || code1 == target_mem_ref_K ||
274  code1 == target_mem_ref461_K)
275  {
276  load_candidate = true;
277  }
278  if(code1 == var_decl_K &&
279  function_behavior->is_variable_mem(GET_INDEX_NODE(GetPointerS<const unary_expr>(op1)->op)))
280  {
281  load_candidate = true;
282  }
283  }
284  auto store_candidate = op0_kind == bit_field_ref_K || op0_kind == component_ref_K ||
285  op0_kind == indirect_ref_K || op0_kind == misaligned_indirect_ref_K ||
286  op0_kind == mem_ref_K || op0_kind == array_ref_K || op0_kind == target_mem_ref_K ||
287  op0_kind == target_mem_ref461_K;
288  if(op0_kind == realpart_expr_K || op0_kind == imagpart_expr_K)
289  {
290  const auto code0 = GET_CONST_NODE(GetPointerS<const unary_expr>(op0)->op)->get_kind();
291  if((code0 == bit_field_ref_K) || code0 == component_ref_K || code0 == indirect_ref_K ||
292  code0 == misaligned_indirect_ref_K || code0 == mem_ref_K || code0 == array_ref_K ||
293  code0 == target_mem_ref_K || code0 == target_mem_ref461_K)
294  {
295  store_candidate = true;
296  }
297  if(code0 == var_decl_K &&
298  function_behavior->is_variable_mem(GET_INDEX_CONST_NODE(GetPointerS<const unary_expr>(op0)->op)))
299  {
300  store_candidate = true;
301  }
302  }
303  if(!gm->clobber && !gm->init_assignment && op0_type && op1_type && op1->get_kind() != insertvalue_expr_K &&
304  op1->get_kind() != extractvalue_expr_K &&
305  ((GET_CONST_NODE(op0_type)->get_kind() == record_type_K &&
306  GET_CONST_NODE(op1_type)->get_kind() == record_type_K && op1_kind != view_convert_expr_K) ||
307  (GET_CONST_NODE(op0_type)->get_kind() == union_type_K &&
308  GET_CONST_NODE(op1_type)->get_kind() == union_type_K && op1_kind != view_convert_expr_K) ||
309  (GET_CONST_NODE(op0_type)->get_kind() == array_type_K) ||
310  (function_behavior->is_variable_mem(GET_INDEX_NODE(gm->op0)) &&
311  function_behavior->is_variable_mem(GET_INDEX_NODE(gm->op1))) ||
312  (function_behavior->is_variable_mem(GET_INDEX_NODE(gm->op0)) && load_candidate) ||
313  (store_candidate && function_behavior->is_variable_mem(GET_INDEX_NODE(gm->op1)))))
314  {
315  if(op0_kind == mem_ref_K)
316  {
317  const auto mr = GetPointerS<const mem_ref>(op0);
318  analyze_node(mr->op0, true, true, false);
319  }
320  else if(op0_kind == target_mem_ref461_K)
321  {
322  const auto tmr = GetPointerS<const target_mem_ref461>(op0);
323  if(tmr->base)
324  {
325  analyze_node(tmr->base, true, true, false);
326  }
327  else
328  {
329  analyze_node(gm->op0, true, true, false);
330  }
331  }
332  else
333  {
334  analyze_node(gm->op0, true, true, false);
335  }
336 
337  if(op1_kind == mem_ref_K)
338  {
339  const auto mr = GetPointerS<const mem_ref>(op1);
340  analyze_node(mr->op0, true, true, false);
341  }
342  else if(op1_kind == target_mem_ref461_K)
343  {
344  const auto tmr = GetPointerS<const target_mem_ref461>(op1);
345  if(tmr->base)
346  {
347  analyze_node(tmr->base, true, true, false);
348  }
349  else
350  {
351  analyze_node(gm->op1, true, true, false);
352  }
353  }
354  else
355  {
356  analyze_node(gm->op1, false, true, false);
357  }
358  if(gm->predicate)
359  {
360  analyze_node(gm->predicate, false, true, false);
361  }
362 
363  if(op1_kind == constructor_K && GetPointerS<const constructor>(op1) &&
364  GetPointerS<const constructor>(op1)->list_of_idx_valu.empty())
365  {
367  const auto ref_var = tree_helper::GetBaseVariable(gm->op0);
368  if(ref_var)
369  {
370  analyze_node(ref_var, true, true, false);
371  }
372  }
373  else
374  {
376  auto ref_var = tree_helper::GetBaseVariable(gm->op0);
377  if(ref_var)
378  {
379  analyze_node(ref_var, true, true, false);
380  }
381  ref_var = tree_helper::GetBaseVariable(gm->op1);
382  if(ref_var)
383  {
384  analyze_node(ref_var, false, true, false);
385  }
386  }
387  }
388  }
389  break;
390  }
392  {
393  const auto ue = GetPointerS<const unary_expr>(tn);
394  const auto ue_op_kind = GET_CONST_NODE(ue->op)->get_kind();
395  if(GetPointer<const addr_expr>(tn))
396  {
397  if(ue_op_kind == var_decl_K)
398  {
399  const auto vd = GetPointerS<const var_decl>(GET_CONST_NODE(ue->op));
400  bool address_externally_used = false;
401  function_behavior->add_function_mem(GET_INDEX_NODE(ue->op));
402  if((((!vd->scpe || GET_NODE(vd->scpe)->get_kind() == translation_unit_decl_K) && !vd->static_flag) ||
404  {
405  if(parameters->isOption(OPT_expose_globals) && parameters->getOption<bool>(OPT_expose_globals))
406  {
407  address_externally_used = true;
408  }
409  function_behavior->set_has_globals(true);
410  function_behavior->add_state_variable(GET_INDEX_NODE(ue->op));
411  if(address_externally_used)
412  {
414  "---Global variable externally accessible found: " +
416  }
417  }
418  else
419  {
420  function_behavior->add_state_variable(GET_INDEX_NODE(ue->op));
421  }
422 
423  if((!no_dynamic_address || address_externally_used))
424  {
426  "---Variable for which the dynamic address is used-1: " +
428  function_behavior->add_dynamic_address(GET_INDEX_NODE(ue->op));
429  if(!vd->readonly_flag)
430  {
431  AppM->add_written_object(GET_INDEX_NODE(ue->op));
432  }
433  }
434  if(left_p && !vd->readonly_flag)
435  {
436  AppM->add_written_object(GET_INDEX_NODE(ue->op));
437  }
438  if(already_visited_ae.find(node_id) == already_visited_ae.end())
439  {
440  already_visited_ae.insert(node_id);
441 
442  if(vd->init && GET_CONST_NODE(vd->init)->get_kind() != string_cst_K)
443  {
444  analyze_node(vd->init, left_p, false, false);
445  }
446  }
447  }
448  else if(ue_op_kind == parm_decl_K)
449  {
450  function_behavior->add_function_mem(GET_INDEX_NODE(ue->op));
451  if(!no_dynamic_address)
452  {
454  "---Variable for which the dynamic address is used-2: " +
456  function_behavior->add_dynamic_address(GET_INDEX_NODE(ue->op));
457  }
460  " Analyzing node: formal parameter copied " + STR(GET_INDEX_NODE(ue->op)));
461  function_behavior->add_parm_decl_copied(GET_INDEX_NODE(ue->op));
462  AppM->add_written_object(GET_INDEX_NODE(ue->op));
463  }
464  else if(ue_op_kind == string_cst_K)
465  {
466  function_behavior->add_function_mem(GET_INDEX_NODE(ue->op));
467  if(!no_dynamic_address)
468  {
470  "---Variable for which the dynamic address is used-3: " +
472  function_behavior->add_dynamic_address(GET_INDEX_NODE(ue->op));
473  AppM->add_written_object(GET_INDEX_NODE(ue->op));
474  }
475  }
476  else if(ue_op_kind == result_decl_K)
477  {
478  function_behavior->add_function_mem(GET_INDEX_NODE(ue->op));
479  if(!no_dynamic_address)
480  {
482  "---Variable for which the dynamic address is used-4: " +
484  function_behavior->add_dynamic_address(GET_INDEX_NODE(ue->op));
485  AppM->add_written_object(GET_INDEX_NODE(ue->op));
486  }
488  "---result_decl variable added to memory: " +
490  }
491  else if(ue_op_kind == component_ref_K || ue_op_kind == realpart_expr_K || ue_op_kind == imagpart_expr_K ||
492  ue_op_kind == array_ref_K)
493  {
494  analyze_node(ue->op, true, !no_dynamic_address, no_dynamic_address);
495  }
496  else if(ue_op_kind == function_decl_K)
497  {
498  analyze_node(ue->op, false, !no_dynamic_address, no_dynamic_address);
499  }
500  else if(ue_op_kind == mem_ref_K)
501  {
502  const auto mr = GetPointerS<const mem_ref>(GET_CONST_NODE(ue->op));
503  analyze_node(mr->op0, left_p, !no_dynamic_address, no_dynamic_address);
504  }
505  else if(ue_op_kind == target_mem_ref461_K)
506  {
507  const auto tmr = GetPointerS<const target_mem_ref461>(GET_CONST_NODE(ue->op));
508  if(tmr->base)
509  {
510  analyze_node(tmr->base, left_p, !no_dynamic_address, no_dynamic_address);
511  }
512  else
513  {
514  analyze_node(ue->op, left_p, !no_dynamic_address, no_dynamic_address);
515  }
516  }
517  else
518  {
520  "determine_memory_accesses addressing currently not supported: " +
521  GET_NODE(ue->op)->get_kind_text() + " @" + STR(node_id) + " in function " +
522  function_name);
523  }
524  }
525  else if(tn_kind == view_convert_expr_K)
526  {
527  const auto vc = GetPointerS<const view_convert_expr>(tn);
528  analyze_node(vc->op, left_p, dynamic_address, no_dynamic_address);
529  }
530  else if(tn_kind == indirect_ref_K)
531  {
532  const auto ir = GetPointerS<const indirect_ref>(tn);
533  if(GetPointer<const integer_cst>(GET_CONST_NODE(ir->op)))
534  {
535  function_behavior->set_dereference_unknown_addr(true);
536  }
537  if(!dynamic_address)
538  {
539  dynamic_address = false;
540  no_dynamic_address = true;
541  }
542  analyze_node(ir->op, left_p, dynamic_address, no_dynamic_address);
543  }
544  else
545  {
546  analyze_node(ue->op, left_p, dynamic_address, no_dynamic_address);
547  }
548  break;
549  }
551  {
552  const auto be = GetPointerS<const binary_expr>(tn);
553  if(tn_kind == mem_ref_K)
554  {
555  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---It is a mem ref");
556  const auto mr = GetPointerS<const mem_ref>(tn);
557  if(GetPointer<const integer_cst>(GET_CONST_NODE(mr->op0)))
558  {
559  function_behavior->set_dereference_unknown_addr(true);
560  }
561  if(!dynamic_address)
562  {
563  dynamic_address = false;
564  no_dynamic_address = true;
565  }
566  if(left_p)
567  {
569  const auto ref_var = tree_helper::GetBaseVariable(mr->op0);
570  if(ref_var)
571  {
572  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Referenced variable is " + STR(ref_var));
573  const bool is_variable_mem = [&]() {
574  if(function_behavior->is_variable_mem(ref_var->index))
575  {
577  "---Already classified as memory variable");
578  return true;
579  }
580  const auto vd = GetPointer<const var_decl>(GET_CONST_NODE(ref_var));
581  if(!vd)
582  {
584  return false;
585  }
586  if(vd->readonly_flag)
587  {
588  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---ReadOnly variable");
589  THROW_ERROR("ReadOnly variable on lhs");
590  return false;
591  }
592  if(vd->static_flag)
593  {
594  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Static variable");
595  return true;
596  }
597  if(!vd->scpe or GET_NODE(vd->scpe)->get_kind() == translation_unit_decl_K)
598  {
600  return true;
601  }
602  if(vd->scpe)
603  {
604  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---local variable of another function");
605  return true;
606  }
607  if(tree_helper::IsVolatile(ref_var))
608  {
610  return true;
611  }
612  const auto type_kind = GET_NODE(vd->type)->get_kind();
613  /*
614  * TODO: the following if should look like this
615  * if (type_kind == array_type_K or type_kind == record_type_K or type_kind == union_type_K)
616  * because the complex types should not be memory allocated
617  * anymore. however changing it results in failures during
618  * allocation due to missing complex components in the
619  * technology library.
620  * This issue should be further investigated.
621  */
622  if(type_kind == array_type_K or type_kind == complex_type_K or type_kind == record_type_K or
623  type_kind == union_type_K)
624  {
625  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Memory allocated");
626  return true;
627  }
628  return false;
629  }();
630  if(is_variable_mem)
631  {
633  AppM->add_written_object(ref_var->index);
634  }
635  }
636  }
637  }
638  analyze_node(be->op0, left_p, dynamic_address, no_dynamic_address);
639  analyze_node(be->op1, left_p, dynamic_address, no_dynamic_address);
640  break;
641  }
642  case gimple_cond_K:
643  {
644  const auto gc = GetPointerS<const gimple_cond>(tn);
645  analyze_node(gc->op0, false, false, true);
646  break;
647  }
648  case gimple_switch_K:
649  {
650  const auto se = GetPointerS<const gimple_switch>(tn);
651  if(se->op0)
652  {
653  analyze_node(se->op0, left_p, dynamic_address, no_dynamic_address);
654  }
655  break;
656  }
657  case gimple_multi_way_if_K:
658  {
659  const auto gmwi = GetPointerS<const gimple_multi_way_if>(tn);
660  for(const auto& cond : gmwi->list_of_cond)
661  {
662  if(cond.first)
663  {
664  analyze_node(cond.first, left_p, dynamic_address, no_dynamic_address);
665  }
666  }
667  break;
668  }
669  case gimple_phi_K:
670  {
671  const auto gp = GetPointerS<const gimple_phi>(tn);
672  for(const auto& def_edge : gp->CGetDefEdgesList())
673  {
674  analyze_node(def_edge.first, left_p, dynamic_address, no_dynamic_address);
675  }
676  break;
677  }
679  {
680  const auto te = GetPointerS<const ternary_expr>(tn);
681  if(tn_kind == component_ref_K)
682  {
683  left_p = true;
684  }
685  if(te->op0)
686  {
687  analyze_node(te->op0, left_p, dynamic_address, no_dynamic_address);
688  }
689  if(te->op1)
690  {
691  analyze_node(te->op1, left_p, dynamic_address, no_dynamic_address);
692  }
693  if(te->op2)
694  {
695  analyze_node(te->op2, left_p, dynamic_address, no_dynamic_address);
696  }
697  break;
698  }
700  {
701  const auto qe = GetPointerS<const quaternary_expr>(tn);
702  if(qe->op0)
703  {
704  analyze_node(qe->op0, left_p, dynamic_address, no_dynamic_address);
705  }
706  if(qe->op1)
707  {
708  analyze_node(qe->op1, left_p, dynamic_address, no_dynamic_address);
709  }
710  if(qe->op2)
711  {
712  analyze_node(qe->op2, left_p, dynamic_address, no_dynamic_address);
713  }
714  if(qe->op3)
715  {
716  analyze_node(qe->op3, left_p, dynamic_address, no_dynamic_address);
717  }
718  break;
719  }
720  case lut_expr_K:
721  {
722  const auto le = GetPointerS<const lut_expr>(tn);
723  analyze_node(le->op0, left_p, dynamic_address, no_dynamic_address);
724  analyze_node(le->op1, left_p, dynamic_address, no_dynamic_address);
725  if(le->op2)
726  {
727  analyze_node(le->op2, left_p, dynamic_address, no_dynamic_address);
728  }
729  if(le->op3)
730  {
731  analyze_node(le->op3, left_p, dynamic_address, no_dynamic_address);
732  }
733  if(le->op4)
734  {
735  analyze_node(le->op4, left_p, dynamic_address, no_dynamic_address);
736  }
737  if(le->op5)
738  {
739  analyze_node(le->op5, left_p, dynamic_address, no_dynamic_address);
740  }
741  if(le->op6)
742  {
743  analyze_node(le->op6, left_p, dynamic_address, no_dynamic_address);
744  }
745  if(le->op7)
746  {
747  analyze_node(le->op7, left_p, dynamic_address, no_dynamic_address);
748  }
749  if(le->op8)
750  {
751  analyze_node(le->op8, left_p, dynamic_address, no_dynamic_address);
752  }
753  break;
754  }
755  case gimple_return_K:
756  {
757  const auto re = GetPointerS<const gimple_return>(tn);
758  if(re->op)
759  {
760  const auto res_type = tree_helper::CGetType(re->op);
761  if(GET_CONST_NODE(res_type)->get_kind() == record_type_K || // records have to be allocated
762  GET_CONST_NODE(res_type)->get_kind() == union_type_K // unions have to be allocated
763  )
764  {
766  "structs or unions returned by copy are not yet supported: @" + STR(node_id) +
767  " in function " + function_name);
768  function_behavior->add_function_mem(node_id);
769  function_behavior->add_parm_decl_copied(node_id);
770  AppM->add_written_object(node_id);
771  }
772  analyze_node(re->op, left_p, dynamic_address, no_dynamic_address);
773  }
774  break;
775  }
776  case call_expr_K:
777  case aggr_init_expr_K:
778  {
779  const auto ce = GetPointerS<const call_expr>(tn);
780  const auto& args = ce->args;
781  const auto ae = GetPointerS<const addr_expr>(GET_CONST_NODE(ce->fn));
782 
783  // The first parameter of a call_expr can be a ssa_name in
784  // case of function pointer usage. When it happens skip the
785  // following analysis.
786  if(!ae)
787  {
788  break;
789  }
790 
791  if(AppM->GetFunctionBehavior(GET_INDEX_NODE(ae->op))->get_unaligned_accesses())
792  {
793  function_behavior->set_unaligned_accesses(true);
794  }
795  const auto fd = GetPointer<function_decl>(GET_CONST_NODE(ae->op));
796  bool is_var_args_p = GetPointer<function_type>(GET_NODE(fd->type))->varargs_flag;
797  THROW_ASSERT(fd, "expected a function_decl");
798  bool has_pointers_as_actual_parameters = false;
799  for(const auto& arg : ce->args)
800  {
801  analyze_node(arg, left_p, dynamic_address, no_dynamic_address);
802  has_pointers_as_actual_parameters |= tree_helper::IsPointerType(arg);
803  }
804  if(!fd->undefined_flag)
805  {
806  if(!(is_var_args_p || fd->list_of_args.size() == args.size()))
807  {
808  THROW_ERROR("In function " + function_name +
809  " a different number of formal and actual parameters is found when function " +
810  tree_helper::GetMangledFunctionName(fd) + " is called: " + STR(fd->list_of_args.size()) +
811  " - " + STR(args.size()) +
812  "\n Check the C source code since an actual parameter is passed to a function that does "
813  "have the associated formal parameter");
814  }
815  auto formal_it = fd->list_of_args.cbegin();
816  const auto formal_it_end = fd->list_of_args.cend();
817  auto arg = ce->args.cbegin();
818  const auto arg_end = ce->args.cend();
819  for(; arg != arg_end && formal_it != formal_it_end; ++arg, ++formal_it)
820  {
821  tree_nodeConstRef actual_par = *arg;
822  const auto formal_par = *formal_it;
823  unsigned int calledFundID = GET_INDEX_NODE(ae->op);
824  if(tree_helper::IsPointerType(actual_par) && tree_helper::GetBaseVariable(actual_par))
825  {
826  actual_par = tree_helper::GetBaseVariable(actual_par);
827  }
828  const auto FBcalled = AppM->GetFunctionBehavior(calledFundID);
830  const auto formal_ssa_index = AppM->getSSAFromParm(calledFundID, formal_par->index);
831  if(function_behavior->is_variable_mem(actual_par->index) && formal_ssa_index)
832  {
833  const auto formal_ssa_node = TM->CGetTreeNode(formal_ssa_index);
834  const auto formal_ssa = GetPointerS<const ssa_name>(formal_ssa_node);
835  const auto is_singleton = formal_ssa->use_set->is_a_singleton() &&
836  actual_par->index == formal_ssa->use_set->variables.front()->index;
837  if(!is_singleton)
838  {
840  "---Variable for which the dynamic address is used-5: " +
841  behavioral_helper->PrintVariable(actual_par->index));
842  function_behavior->add_dynamic_address(actual_par->index);
843  AppM->add_written_object(actual_par->index);
845  if(!FBcalled->is_variable_mem(formal_par->index) && GET_INDEX_NODE(*arg) == actual_par->index)
846  {
848  " Analyzing node: actual parameter loaded " + STR(actual_par));
849  function_behavior->add_parm_decl_loaded(actual_par->index);
850  }
851  }
852  }
853  else if(!formal_ssa_index)
854  {
856  "---Parameter is not used in the function body.");
857  }
858 
860  if(FBcalled->is_variable_mem(formal_par->index))
861  {
864  const auto actual_par_node = GET_CONST_NODE(*arg);
865  switch(actual_par->get_kind())
866  {
867  case ssa_name_K:
868  {
869  if(!function_behavior->is_variable_mem(actual_par->index))
870  {
872  " Analyzing node: formal parameter stored " + STR(formal_par->index));
873  FBcalled->add_parm_decl_stored(formal_par->index);
874  FBcalled->add_dynamic_address(formal_par->index);
875  AppM->add_written_object(formal_par->index);
876  }
877  break;
878  }
879  case real_cst_K:
880  case string_cst_K:
881  case integer_cst_K:
882  case addr_expr_K:
883  {
885  " Analyzing node: formal parameter stored " + STR(formal_par->index));
886  FBcalled->add_parm_decl_stored(formal_par->index);
887  FBcalled->add_dynamic_address(formal_par->index);
888  AppM->add_written_object(formal_par->index);
889  if(actual_par->get_kind() == string_cst_K)
890  {
892  "---Variable for which the dynamic address is used-6: " +
893  behavioral_helper->PrintVariable(actual_par->index));
894  function_behavior->add_dynamic_address(actual_par->index);
895  AppM->add_written_object(actual_par->index);
896  }
897  break;
898  }
899  case misaligned_indirect_ref_K:
900  case indirect_ref_K:
901  case array_ref_K:
902  case component_ref_K:
903  {
905  " Analyzing node: formal parameter copied " + STR(formal_par->index));
906  FBcalled->add_parm_decl_copied(formal_par->index);
907  FBcalled->add_dynamic_address(formal_par->index);
908  AppM->add_written_object(formal_par->index);
909  const auto arg_op_type = tree_helper::CGetType(actual_par_node);
910  if(GET_CONST_NODE(arg_op_type)->get_kind() == record_type_K || // records have to be allocated
911  GET_CONST_NODE(arg_op_type)->get_kind() == union_type_K // unions have to be allocated
912  )
913  {
914  analyze_node(actual_par, left_p, true, false);
915  }
916  break;
917  }
918  case binfo_K:
919  case block_K:
920  case call_expr_K:
921  case aggr_init_expr_K:
922  case case_label_expr_K:
923  case constructor_K:
924  case identifier_node_K:
925  case statement_list_K:
926  case target_mem_ref_K:
927  case target_mem_ref461_K:
928  case tree_list_K:
929  case tree_vec_K:
930  case abs_expr_K:
931  case alignof_expr_K:
932  case arrow_expr_K:
933  case bit_not_expr_K:
934  case buffer_ref_K:
935  case card_expr_K:
936  case cleanup_point_expr_K:
937  case conj_expr_K:
938  case convert_expr_K:
939  case exit_expr_K:
940  case fix_ceil_expr_K:
941  case fix_floor_expr_K:
942  case fix_round_expr_K:
943  case fix_trunc_expr_K:
944  case float_expr_K:
945  case imagpart_expr_K:
946  case loop_expr_K:
947  case negate_expr_K:
948  case non_lvalue_expr_K:
949  case nop_expr_K:
950  case paren_expr_K:
951  case realpart_expr_K:
952  case reference_expr_K:
953  case reinterpret_cast_expr_K:
954  case sizeof_expr_K:
955  case static_cast_expr_K:
956  case throw_expr_K:
957  case truth_not_expr_K:
958  case unsave_expr_K:
959  case va_arg_expr_K:
960  case view_convert_expr_K:
961  case reduc_max_expr_K:
962  case reduc_min_expr_K:
963  case reduc_plus_expr_K:
964  case vec_unpack_hi_expr_K:
965  case vec_unpack_lo_expr_K:
966  case vec_unpack_float_hi_expr_K:
967  case vec_unpack_float_lo_expr_K:
968  case bit_field_ref_K:
969  case vtable_ref_K:
970  case with_cleanup_expr_K:
971  case obj_type_ref_K:
972  case save_expr_K:
973  case cond_expr_K:
974  case vec_cond_expr_K:
975  case vec_perm_expr_K:
976  case dot_prod_expr_K:
977  case ternary_plus_expr_K:
978  case ternary_pm_expr_K:
979  case ternary_mp_expr_K:
980  case ternary_mm_expr_K:
981  case fshl_expr_K:
982  case fshr_expr_K:
983  case bit_ior_concat_expr_K:
984  case complex_cst_K:
985  case vector_cst_K:
986  case void_cst_K:
987  case array_range_ref_K:
988  case target_expr_K:
989  case error_mark_K:
990  case lut_expr_K:
991  case insertvalue_expr_K:
992  case insertelement_expr_K:
994  case CASE_CPP_NODES:
995  case CASE_DECL_NODES:
996  case CASE_FAKE_NODES:
997  case CASE_GIMPLE_NODES:
998  case CASE_PRAGMA_NODES:
999  case CASE_TYPE_NODES:
1000  default:
1001  {
1002  THROW_ASSERT(function_behavior->is_variable_mem(actual_par->index),
1003  "actual parameter non allocated in memory: calling @" + STR(calledFundID) +
1004  " actual " + actual_par->ToString());
1005  break;
1006  }
1007  }
1008  }
1009  }
1010  }
1011  else
1012  {
1013  if(has_pointers_as_actual_parameters)
1014  {
1015  function_behavior->set_has_undefined_function_receiveing_pointers(true);
1016  function_behavior->set_unaligned_accesses(true);
1017  }
1018  }
1019  break;
1020  }
1021  case gimple_call_K:
1022  {
1023  const auto ce = GetPointerS<const gimple_call>(tn);
1024  const auto ae = GetPointerS<const addr_expr>(GET_CONST_NODE(ce->fn));
1025  // The first parameter of a call_expr can be a ssa_name in
1026  // case of function pointer usage. When it happens skip the
1027  // following analysis.
1028  if(!ae)
1029  {
1030  break;
1031  }
1032 
1033  const auto fd = GetPointerS<const function_decl>(GET_CONST_NODE(ae->op));
1035  {
1036  function_behavior->add_function_mem(node_id);
1037  AppM->add_written_object(node_id);
1038  }
1039 
1040  bool is_var_args_p = GetPointer<function_type>(GET_NODE(fd->type))->varargs_flag;
1041  THROW_ASSERT(fd, "expected a function_decl");
1042  bool has_pointers_as_actual_parameters = false;
1043  for(const auto& arg : ce->args)
1044  {
1045  analyze_node(arg, left_p, dynamic_address, no_dynamic_address);
1046  has_pointers_as_actual_parameters |= tree_helper::IsPointerType(arg);
1047  }
1048  if(!fd->undefined_flag)
1049  {
1050  if(!(is_var_args_p || fd->list_of_args.size() == ce->args.size()))
1051  {
1052  THROW_ERROR("In function " + function_name +
1053  " a different number of formal and actual parameters is found when function " +
1054  tree_helper::GetMangledFunctionName(fd) + " is called: " + STR(fd->list_of_args.size()) +
1055  " - " + STR(ce->args.size()) +
1056  "\n Check the C source code since an actual parameter is passed to a function that does "
1057  "have the associated formal parameter");
1058  }
1059  auto formal_it = fd->list_of_args.cbegin();
1060  const auto formal_it_end = fd->list_of_args.cend();
1061  auto arg = ce->args.cbegin();
1062  const auto arg_end = ce->args.cend();
1063  for(; arg != arg_end && formal_it != formal_it_end; ++arg, ++formal_it)
1064  {
1065  tree_nodeConstRef actual_par = *arg;
1066  const auto formal_par = *formal_it;
1067  unsigned int calledFundID = GET_INDEX_NODE(ae->op);
1068  if(tree_helper::IsPointerType(actual_par) && tree_helper::GetBaseVariable(actual_par))
1069  {
1070  actual_par = tree_helper::GetBaseVariable(actual_par);
1071  }
1072  const auto FBcalled = AppM->GetFunctionBehavior(calledFundID);
1074  const auto formal_ssa_index = AppM->getSSAFromParm(calledFundID, formal_par->index);
1075  if(function_behavior->is_variable_mem(actual_par->index) && formal_ssa_index)
1076  {
1077  const auto formal_ssa_node = TM->CGetTreeNode(formal_ssa_index);
1078  const auto formal_ssa = GetPointer<const ssa_name>(formal_ssa_node);
1079  const auto is_singleton = formal_ssa->use_set->is_a_singleton() &&
1080  actual_par->index == formal_ssa->use_set->variables.front()->index;
1081  if(!is_singleton)
1082  {
1084  "---Variable for which the dynamic address is used-7: " +
1085  behavioral_helper->PrintVariable(actual_par->index));
1086  function_behavior->add_dynamic_address(actual_par->index);
1087  AppM->add_written_object(actual_par->index);
1089  if(!FBcalled->is_variable_mem(formal_par->index) &&
1090  GET_INDEX_CONST_NODE(*arg) == actual_par->index)
1091  {
1093  "---actual parameter loaded " + STR(actual_par->index));
1094  function_behavior->add_parm_decl_loaded(actual_par->index);
1095  }
1096  }
1097  }
1098  else if(!formal_ssa_index)
1099  {
1101  "---Parameter is not used in the function body.");
1102  }
1104  if(FBcalled->is_variable_mem(formal_par->index))
1105  {
1108  const auto actual_par_node = GET_CONST_NODE(*arg);
1109  switch(actual_par->get_kind())
1110  {
1111  case ssa_name_K:
1112  {
1113  if(!function_behavior->is_variable_mem(actual_par->index))
1114  {
1116  "---formal parameter stored " + STR(formal_par->index));
1117  FBcalled->add_parm_decl_stored(formal_par->index);
1118  FBcalled->add_dynamic_address(formal_par->index);
1119  AppM->add_written_object(formal_par->index);
1120  }
1121  break;
1122  }
1123  case real_cst_K:
1124  case string_cst_K:
1125  case integer_cst_K:
1126  case addr_expr_K:
1127  {
1129  "---formal parameter stored " + STR(formal_par->index));
1130  FBcalled->add_parm_decl_stored(formal_par->index);
1131  FBcalled->add_dynamic_address(formal_par->index);
1132  AppM->add_written_object(formal_par->index);
1133  if(actual_par->get_kind() == string_cst_K)
1134  {
1135  function_behavior->add_dynamic_address(actual_par->index);
1136  AppM->add_written_object(actual_par->index);
1137  }
1138  break;
1139  }
1140  case misaligned_indirect_ref_K:
1141  case indirect_ref_K:
1142  case array_ref_K:
1143  case component_ref_K:
1144  {
1146  "---formal parameter copied " + STR(formal_par->index));
1147  FBcalled->add_parm_decl_copied(formal_par->index);
1148  FBcalled->add_dynamic_address(formal_par->index);
1149  AppM->add_written_object(formal_par->index);
1150  const auto arg_op_type = tree_helper::CGetType(actual_par_node);
1151  if(GET_CONST_NODE(arg_op_type)->get_kind() == record_type_K || // records have to be allocated
1152  GET_CONST_NODE(arg_op_type)->get_kind() == union_type_K // unions have to be allocated
1153  )
1154  {
1155  analyze_node(actual_par, left_p, true, false);
1156  }
1157  break;
1158  }
1159  case binfo_K:
1160  case block_K:
1161  case call_expr_K:
1162  case aggr_init_expr_K:
1163  case case_label_expr_K:
1164  case constructor_K:
1165  case identifier_node_K:
1166  case statement_list_K:
1167  case target_mem_ref_K:
1168  case target_mem_ref461_K:
1169  case tree_list_K:
1170  case tree_vec_K:
1171  case abs_expr_K:
1172  case alignof_expr_K:
1173  case arrow_expr_K:
1174  case bit_not_expr_K:
1175  case buffer_ref_K:
1176  case card_expr_K:
1177  case cleanup_point_expr_K:
1178  case conj_expr_K:
1179  case convert_expr_K:
1180  case exit_expr_K:
1181  case fix_ceil_expr_K:
1182  case fix_floor_expr_K:
1183  case fix_round_expr_K:
1184  case fix_trunc_expr_K:
1185  case float_expr_K:
1186  case imagpart_expr_K:
1187  case loop_expr_K:
1188  case negate_expr_K:
1189  case non_lvalue_expr_K:
1190  case nop_expr_K:
1191  case paren_expr_K:
1192  case realpart_expr_K:
1193  case reference_expr_K:
1194  case reinterpret_cast_expr_K:
1195  case sizeof_expr_K:
1196  case static_cast_expr_K:
1197  case throw_expr_K:
1198  case truth_not_expr_K:
1199  case unsave_expr_K:
1200  case va_arg_expr_K:
1201  case view_convert_expr_K:
1202  case reduc_max_expr_K:
1203  case reduc_min_expr_K:
1204  case reduc_plus_expr_K:
1205  case vec_unpack_hi_expr_K:
1206  case vec_unpack_lo_expr_K:
1207  case vec_unpack_float_hi_expr_K:
1208  case vec_unpack_float_lo_expr_K:
1209  case bit_field_ref_K:
1210  case vtable_ref_K:
1211  case with_cleanup_expr_K:
1212  case obj_type_ref_K:
1213  case save_expr_K:
1214  case cond_expr_K:
1215  case dot_prod_expr_K:
1216  case ternary_plus_expr_K:
1217  case ternary_pm_expr_K:
1218  case ternary_mp_expr_K:
1219  case ternary_mm_expr_K:
1220  case fshl_expr_K:
1221  case fshr_expr_K:
1222  case bit_ior_concat_expr_K:
1223  case vec_cond_expr_K:
1224  case vec_perm_expr_K:
1225  case complex_cst_K:
1226  case vector_cst_K:
1227  case void_cst_K:
1228  case array_range_ref_K:
1229  case target_expr_K:
1230  case error_mark_K:
1231  case lut_expr_K:
1232  case insertvalue_expr_K:
1233  case insertelement_expr_K:
1235  case CASE_CPP_NODES:
1236  case CASE_DECL_NODES:
1237  case CASE_FAKE_NODES:
1238  case CASE_GIMPLE_NODES:
1239  case CASE_PRAGMA_NODES:
1240  case CASE_TYPE_NODES:
1241  default:
1242  {
1243  THROW_ASSERT(function_behavior->is_variable_mem(actual_par->index),
1244  "actual parameter non allocated in memory: calling @" + STR(calledFundID) +
1245  " actual " + actual_par->ToString());
1246  break;
1247  }
1248  }
1249  }
1250  }
1251  }
1252  else
1253  {
1254  if(has_pointers_as_actual_parameters)
1255  {
1256  function_behavior->set_has_undefined_function_receiveing_pointers(true);
1257  function_behavior->set_unaligned_accesses(true);
1258  }
1259  }
1260  break;
1261  }
1262  case ssa_name_K:
1263  {
1264  const auto sn = GetPointerS<const ssa_name>(tn);
1265  if(sn->use_set->is_fully_resolved())
1266  {
1267  for(const auto& var : sn->use_set->variables)
1268  {
1269  function_behavior->add_function_mem(var->index);
1270  }
1271  }
1272  break;
1273  }
1274  case vector_cst_K:
1275  case void_cst_K:
1276  case real_cst_K:
1277  case integer_cst_K:
1278  case gimple_label_K:
1279  case label_decl_K:
1280  case complex_cst_K:
1281  {
1282  break;
1283  }
1284  case string_cst_K:
1285  {
1286  function_behavior->add_function_mem(node_id);
1287  if(dynamic_address && !no_dynamic_address)
1288  {
1290  "---Variable for which the dynamic address is used-8: " +
1291  behavioral_helper->PrintVariable(node_id));
1292  function_behavior->add_dynamic_address(node_id);
1293  AppM->add_written_object(node_id);
1294  }
1295  if(left_p)
1296  {
1297  AppM->add_written_object(node_id);
1298  }
1299  break;
1300  }
1301  case parm_decl_K:
1302  {
1303  const auto pd = GetPointerS<const parm_decl>(tn);
1304  if(GET_NODE(pd->type)->get_kind() == record_type_K || // records have to be allocated
1305  GET_NODE(pd->type)->get_kind() == union_type_K // unions have to be allocated
1306  )
1307  {
1309  "---Variable for which the dynamic address is used-9: " +
1310  behavioral_helper->PrintVariable(node_id));
1311  function_behavior->add_function_mem(node_id);
1312  function_behavior->add_dynamic_address(node_id);
1313  AppM->add_written_object(node_id);
1314  if(left_p)
1315  {
1317  " Analyzing node: formal parameter copied " + STR(node_id));
1318  function_behavior->add_parm_decl_copied(node_id);
1319  }
1320  }
1321  break;
1322  }
1323  case result_decl_K:
1324  {
1325  const auto rd = GetPointerS<const result_decl>(tn);
1326  if(GET_NODE(rd->type)->get_kind() == record_type_K || // records have to be allocated
1327  GET_NODE(rd->type)->get_kind() == union_type_K // unions have to be allocated
1328  )
1329  {
1330  THROW_ERROR_CODE(C_EC, "structs or unions returned by copy are not yet supported: @" + STR(node_id) +
1331  " in function " + function_name);
1332  function_behavior->add_function_mem(node_id);
1333  function_behavior->add_parm_decl_copied(node_id);
1334  AppM->add_written_object(node_id);
1335  }
1336  break;
1337  }
1338  case tree_list_K:
1339  {
1340  auto tl = GetPointerS<const tree_list>(tn);
1341  while(tl)
1342  {
1343  analyze_node(tl->valu, left_p, dynamic_address, no_dynamic_address);
1344  tl = tl->chan ? GetPointerS<const tree_list>(GET_CONST_NODE(tl->chan)) : nullptr;
1345  }
1346  break;
1347  }
1348  case var_decl_K:
1349  {
1350  const auto vd = GetPointerS<const var_decl>(tn);
1351  if(vd->extern_flag)
1352  {
1353  THROW_ERROR_CODE(C_EC, "Extern symbols not yet supported " + behavioral_helper->PrintVariable(node_id));
1354  }
1355  if(!vd->scpe || GET_NODE(vd->scpe)->get_kind() ==
1356  translation_unit_decl_K) // memory has to be allocated in case of global variables
1357  {
1358  function_behavior->add_function_mem(node_id);
1359  bool address_externally_used = false;
1360  if((!vd->static_flag || tree_helper::IsVolatile(tn)))
1361  {
1362  if(parameters->isOption(OPT_expose_globals) && parameters->getOption<bool>(OPT_expose_globals))
1363  {
1364  address_externally_used = true;
1365  }
1366  function_behavior->set_has_globals(true);
1367  if(address_externally_used)
1368  {
1370  "---Global variable externally accessible found: " +
1371  behavioral_helper->PrintVariable(node_id));
1372  }
1373  }
1374  function_behavior->add_state_variable(node_id);
1375  if((dynamic_address && !no_dynamic_address && !vd->addr_not_taken) || address_externally_used ||
1376  vd->addr_taken)
1377  {
1379  "---Variable for which the dynamic address is used-10: " +
1380  behavioral_helper->PrintVariable(node_id));
1381  function_behavior->add_dynamic_address(node_id);
1382  if(!vd->readonly_flag)
1383  {
1384  AppM->add_written_object(node_id);
1385  }
1386  }
1387  if(left_p && !vd->readonly_flag)
1388  {
1389  AppM->add_written_object(node_id);
1390  }
1391  if(vd->init && (GET_CONST_NODE(vd->init)->get_kind() != string_cst_K))
1392  {
1393  analyze_node(vd->init, false, false, false);
1394  }
1395  }
1396  else
1397  {
1398  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Local variable");
1399  THROW_ASSERT(GET_NODE(vd->scpe)->get_kind() != translation_unit_decl_K,
1400  "translation_unit_decl not expected a translation unit in this point @" + STR(node_id));
1401  if(vd->static_flag || // memory has to be allocated in case of local static variables
1402  tree_helper::IsVolatile(tn) || // volatile vars have to be allocated
1403  GET_NODE(vd->type)->get_kind() == array_type_K || // arrays have to be allocated
1404  /*
1405  * TODO: initially complexes were like structs and so they were allocated
1406  * this should not happen anymore but removing the next line
1407  * caused failures in the allocation due to missing complex
1408  * components in the technology library.
1409  * This issue should be further investigated.
1410  */
1411  GET_NODE(vd->type)->get_kind() == complex_type_K ||
1412  GET_NODE(vd->type)->get_kind() == record_type_K || // records have to be allocated
1413  GET_NODE(vd->type)->get_kind() == union_type_K)
1414  {
1415  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---It has to be allocated");
1416  bool address_externally_used = false;
1417  if(tree_helper::IsVolatile(tn))
1418  {
1419  if(parameters->isOption(OPT_expose_globals) && parameters->getOption<bool>(OPT_expose_globals))
1420  {
1421  address_externally_used = true;
1422  }
1423  function_behavior->set_has_globals(true);
1424  function_behavior->add_state_variable(node_id);
1425  if(address_externally_used)
1426  {
1428  "---Global variable externally accessible found: " +
1429  behavioral_helper->PrintVariable(node_id));
1430  }
1431  }
1432  else if(vd->static_flag)
1433  {
1434  function_behavior->add_state_variable(node_id);
1435  }
1436  function_behavior->add_function_mem(node_id);
1437  if((dynamic_address && !no_dynamic_address && !vd->addr_not_taken) || address_externally_used ||
1438  vd->addr_taken)
1439  {
1441  "---Variable for which the dynamic address is used-11: " +
1442  behavioral_helper->PrintVariable(node_id));
1443  function_behavior->add_dynamic_address(node_id);
1444  if(!vd->readonly_flag)
1445  {
1446  AppM->add_written_object(node_id);
1447  }
1448  }
1449  if(left_p && !vd->readonly_flag)
1450  {
1451  AppM->add_written_object(node_id);
1452  }
1453  }
1454  else
1455  {
1456  // nothing have to be allocated for the variable
1457  // maybe something has to be allocated for its initialization
1458  if(vd->init && GET_CONST_NODE(vd->init)->get_kind() != string_cst_K)
1459  {
1460  analyze_node(vd->init, left_p, false, false);
1461  }
1462  }
1463  }
1464  break;
1465  }
1466  case constructor_K:
1467  {
1468  const auto con = GetPointerS<const constructor>(tn);
1469  for(const auto& el : con->list_of_idx_valu)
1470  {
1471  if(el.first)
1472  {
1473  analyze_node(el.first, left_p, dynamic_address, no_dynamic_address);
1474  }
1475  if(el.second)
1476  {
1477  analyze_node(el.second, left_p, dynamic_address, no_dynamic_address);
1478  }
1479  }
1480  break;
1481  }
1482  case gimple_goto_K:
1483  {
1484  const auto ge = GetPointerS<const gimple_goto>(tn);
1485  analyze_node(ge->op, left_p, dynamic_address, no_dynamic_address);
1486  break;
1487  }
1488  case gimple_nop_K:
1489  case field_decl_K:
1490  case gimple_pragma_K:
1491  case CASE_PRAGMA_NODES:
1492  {
1493  break;
1494  }
1495  case target_mem_ref_K:
1496  {
1497  const auto tmr = GetPointerS<const target_mem_ref>(tn);
1498  if(tmr->symbol)
1499  {
1500  analyze_node(tmr->symbol, left_p, false, true);
1501  }
1502  if(tmr->base)
1503  {
1504  analyze_node(tmr->base, left_p, false, true);
1505  }
1506  if(tmr->idx)
1507  {
1508  analyze_node(tmr->idx, left_p, false, false);
1509  }
1510  break;
1511  }
1512  case target_mem_ref461_K:
1513  {
1514  const auto tmr = GetPointerS<const target_mem_ref461>(tn);
1515  if(tmr->base)
1516  {
1517  const auto operand = GET_CONST_NODE(tmr->base);
1518  if(operand->get_kind() == addr_expr_K)
1519  {
1521  analyze_node(GetPointerS<const addr_expr>(operand)->op, left_p, false, true);
1522  }
1523  else
1524  {
1525  analyze_node(tmr->base, left_p, false, true);
1526  }
1527  }
1528  if(tmr->idx)
1529  {
1530  analyze_node(tmr->idx, left_p, false, false);
1531  }
1532  if(tmr->idx2)
1533  {
1534  analyze_node(tmr->idx2, left_p, false, false);
1535  }
1536 
1538  // if(tmr->base)
1539  // {
1540  // const auto type_base = tree_helper::CGetType(tmr->base);
1541  // const auto t_base_ptr = GetPointer<const type_node>(GET_CONST_NODE(type_base));
1542  // if(t_base_ptr->algn != 8)
1543  // {
1544  // }
1545  // }
1546  break;
1547  }
1548  case function_decl_K:
1549  case template_decl_K:
1550  {
1551  break;
1552  }
1553  case gimple_asm_K:
1554  {
1555  const auto ga = GetPointerS<const gimple_asm>(tn);
1556  if(ga->in)
1557  {
1558  analyze_node(ga->in, false, false, false);
1559  }
1560  if(ga->out)
1561  {
1562  analyze_node(ga->out, true, false, false);
1563  }
1564  break;
1565  }
1566  case binfo_K:
1567  case block_K:
1568  case case_label_expr_K:
1569  case const_decl_K:
1570  case CASE_CPP_NODES:
1571  case CASE_FAKE_NODES:
1572  case gimple_for_K:
1573  case gimple_bind_K:
1574  case gimple_predict_K:
1575  case gimple_resx_K:
1576  case gimple_while_K:
1577  case identifier_node_K:
1578  case namespace_decl_K:
1579  case statement_list_K:
1580  case translation_unit_decl_K:
1581  case error_mark_K:
1582  case using_decl_K:
1583  case tree_vec_K:
1584  case type_decl_K:
1585  case CASE_TYPE_NODES:
1586  case target_expr_K:
1587  {
1588  THROW_ERROR_CODE(NODE_NOT_YET_SUPPORTED_EC, "Not supported node (@" + STR(node_id) + ") of type " +
1589  std::string(tn->get_kind_text()) + " in function " +
1590  function_name);
1591  break;
1592  }
1593  default:
1594  {
1595  THROW_UNREACHABLE("");
1596  }
1597  }
1598  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Analyzed node " + tn->ToString());
1599 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
#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.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
std::string ToString() const
Print this node as string in gimple format.
#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.
std::string get_function_name() const
Return the name of the function.
#define BB_EXIT
constant identifying the basic block node of type exit
Definition of the class representing a generic C application.
CustomUnorderedSet< unsigned int > already_visited_ae
Already visited address expression (used to avoid infinite recursion)
const int output_level
The output level.
#define CASE_DECL_NODES
NOTE that cast_expr is a unary expression but it could not be included in the CASE_UNARY_EXPRESSION b...
Definition: tree_node.hpp:672
const BehavioralHelperConstRef behavioral_helper
The behavioral helper.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
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.
Determine variables to be stored in memory.
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
DesignFlowStep_Status InternalExec() override
Determines the variables that require a memory access.
Base class to model interfaces for high-level synthesis.
#define BUILTIN_WAIT_CALL
constant defining the builtin wait call intrinsic function
Definition: op_graph.hpp:358
static bool IsVolatile(const tree_nodeConstRef &tn)
return true in case the tree node corresponds to a volatile variable
#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
static std::string print_function_name(const tree_managerConstRef &TM, const function_decl *fd)
Return the name of the function in a string.
Node not yet supported.
Definition: exceptions.hpp:323
Data structure describing a basic block at tree level.
static std::string GetMangledFunctionName(const function_decl *fd)
Return the mangled function name.
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.
~determine_memory_accesses() override
Destructor.
C pattern not supported.
Definition: exceptions.hpp:337
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
#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
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 BB_ENTRY
constant identifying the basic block node of type entry
determine_memory_accesses(const ParameterConstRef parameters, const application_managerRef AppM, unsigned int _function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
static bool IsVectorType(const tree_nodeConstRef &type)
Return true if the treenode is a vector.
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
Classes specification of the tree_node data structures.
void analyze_node(const tree_nodeConstRef &tn, bool left_p, bool dynamic_address, bool no_dynamic_address)
Analyze the given node ID to determine which variables have to be referred in memory.
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.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
std::string PrintVariable(unsigned int var) const
Print the name of the variable associated to the index.
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
Definition: tree_node.hpp:581
This file collects some utility functions.
const unsigned int function_id
The index of the function to be analyzed.
static tree_nodeConstRef GetBaseVariable(const tree_nodeConstRef &mem)
Retrun the base variable of a memory access.
const application_managerRef AppM
The application manager.
int el
Definition: adpcm.c:105
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
CustomUnorderedSet< unsigned int > already_visited
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.
#define THROW_ERROR_CODE(code, str_expr)
helper function used to throw an error with a code error
Definition: exceptions.hpp:266
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
const tree_managerConstRef TM
The tree manager.
Wrapper to call graph.
#define CASE_GIMPLE_NODES
This macro collects all cases labels for gimple nodes.
Definition: tree_node.hpp:700
int debug_level
The debug level.
#define OUTPUT_LEVEL_VERBOSE
verbose debugging print is performed.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
static bool IsPointerType(const tree_nodeConstRef &type)
Return true if treenode index is a pointer.
#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.
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 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