PandA-2024.02
rebuild_initializations.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  */
46 
47 #include "Parameter.hpp"
48 #include "application_manager.hpp"
49 #include "basic_block.hpp"
50 #include "behavioral_helper.hpp"
51 #include "custom_map.hpp"
52 #include "custom_set.hpp"
53 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
54 #include "function_behavior.hpp"
55 #include "string_manipulation.hpp" // for GET_CLASS
56 #include "token_interface.hpp"
57 #include "tree_basic_block.hpp"
58 #include "tree_helper.hpp"
59 #include "tree_manager.hpp"
60 #include "tree_manipulation.hpp"
61 #include "tree_reindex.hpp"
62 
64 #include <fstream>
65 #include <utility>
66 #include <vector>
67 
69  unsigned int _function_id,
70  const DesignFlowManagerConstRef _design_flow_manager)
71  : FunctionFrontendFlowStep(_AppM, _function_id, REBUILD_INITIALIZATION, _design_flow_manager, Param)
72 {
73  debug_level = Param->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
74 }
75 
78 {
80  switch(relationship_type)
81  {
85  {
86  break;
87  }
88  default:
90  }
91  return relationships;
92 }
93 
95 
97 {
98  const auto behavioral_helper = function_behavior->CGetBehavioralHelper();
99  tree_managerRef TM = AppM->get_tree_manager();
102  auto* fd = GetPointerS<function_decl>(tn);
103  THROW_ASSERT(fd && fd->body, "Node is not a function or it hasn't a body");
104  auto* sl = GetPointerS<statement_list>(GET_NODE(fd->body));
105  THROW_ASSERT(sl, "Body is not a statement_list");
106  auto B_it_end = sl->list_of_bloc.end();
107 
109 
111  for(auto B_it = sl->list_of_bloc.begin(); B_it != B_it_end; ++B_it)
112  {
113  blocRef B = B_it->second;
114  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining BB" + STR(B->number));
115  const auto& list_of_stmt = B->CGetStmtList();
116  auto it_los_end = list_of_stmt.end();
117  auto it_los = list_of_stmt.begin();
118  while(it_los != it_los_end)
119  {
121  "-->Examining statement " + GET_NODE(*it_los)->ToString());
122  if(GET_NODE(*it_los)->get_kind() == gimple_assign_K)
123  {
124  auto* ga = GetPointerS<gimple_assign>(GET_NODE(*it_los));
125  enum kind code0 = GET_NODE(ga->op0)->get_kind();
127  "Left part of assignment " + GET_NODE(ga->op0)->get_kind_text() +
128  (code0 == array_ref_K ?
129  " - Type is " + GET_CONST_NODE(tree_helper::CGetType(ga->op0))->get_kind_text() :
130  ""));
131 
134  if(code0 == array_ref_K && GET_CONST_NODE(tree_helper::CGetType(ga->op0))->get_kind() == integer_type_K)
135  {
137  "check for an initialization such as var[const_index] = const_value; " +
138  STR(GET_INDEX_NODE(ga->op0)));
139  auto* ar = GetPointerS<array_ref>(GET_NODE(ga->op0));
140  if(GET_NODE(ar->op0)->get_kind() == var_decl_K && GET_NODE(ar->op1)->get_kind() == integer_cst_K)
141  {
142  auto* vd = GetPointerS<var_decl>(GET_NODE(ar->op0));
143  if(vd->readonly_flag)
144  {
145  THROW_ASSERT(!vd->init, "Writing element of read only array already initialized: " + STR(ga->op0));
146  inits[ar->op0][tree_helper::GetConstValue(ar->op1)] = ga->op1;
148  "<--Statement removed " + GET_NODE(*it_los)->ToString());
149  if(ga->memdef)
150  {
151  const auto gimple_nop_id = TM->new_tree_node_id();
152  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> gimple_nop_schema;
153  gimple_nop_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
154  gimple_nop_schema[TOK(TOK_SCPE)] = STR(function_id);
155  TM->create_tree_node(gimple_nop_id, gimple_nop_K, gimple_nop_schema);
156  GetPointerS<ssa_name>(GET_NODE(ga->memdef))->SetDefStmt(TM->GetTreeReindex(gimple_nop_id));
157  }
158  if(ga->vdef)
159  {
160  const auto gimple_nop_id = TM->new_tree_node_id();
161  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> gimple_nop_schema;
162  gimple_nop_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
163  gimple_nop_schema[TOK(TOK_SCPE)] = STR(function_id);
164  TM->create_tree_node(gimple_nop_id, gimple_nop_K, gimple_nop_schema);
165  GetPointerS<ssa_name>(GET_NODE(ga->vdef))->SetDefStmt(TM->GetTreeReindex(gimple_nop_id));
166  }
167  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Removing " + STR(*it_los));
168  B->RemoveStmt(*it_los, AppM);
169  it_los = list_of_stmt.begin();
170  it_los_end = list_of_stmt.end();
171  continue;
172  }
173  }
174  }
175  }
177  "<--Examined statement " + GET_NODE(*it_los)->ToString());
178  ++it_los;
179  }
180 
181  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined BB" + STR(B->number));
182  }
183  const auto integer_type = tree_man->GetSignedIntegerType();
184  for(const auto& init : inits)
185  {
186  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Rebuilding init of " + STR(init.first));
187  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> constructor_tree_node_schema;
188  const auto array_type = tree_helper::CGetType(init.first);
189  constructor_tree_node_schema[TOK(TOK_TYPE)] = STR(array_type->index);
191  const auto element_type = tree_helper::CGetElements(array_type);
192  auto constructor_index = TM->new_tree_node_id();
193  TM->create_tree_node(constructor_index, constructor_K, constructor_tree_node_schema);
194  auto* constr = GetPointerS<constructor>(TM->GetTreeNode(constructor_index));
195  const auto last_index = init.second.rbegin()->first;
196  integer_cst_t index = 0;
197  for(index = 0; index <= last_index; index++)
198  {
200  if(init.second.count(index))
201  {
202  constr->add_idx_valu(TM->CreateUniqueIntegerCst(index, integer_type), init.second.at(index));
203  }
204  else
205  {
206  THROW_ASSERT(GET_CONST_NODE(element_type)->get_kind() == integer_type_K,
207  "Type not supported " + STR(element_type));
208  const auto default_value = TM->CreateUniqueIntegerCst(0, element_type);
209  constr->add_idx_valu(TM->CreateUniqueIntegerCst(index, integer_type), default_value);
210  }
211  }
212  GetPointerS<var_decl>(GET_NODE(init.first))->init = TM->GetTreeReindex(constructor_index);
213  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Rebuilt init of " + STR(init.first));
214  }
216 }
217 
219  unsigned int _function_id,
220  const DesignFlowManagerConstRef _design_flow_manager)
221  : FunctionFrontendFlowStep(_AppM, _function_id, REBUILD_INITIALIZATION2, _design_flow_manager, Param)
222 {
223  debug_level = Param->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
224 }
225 
228 {
230  switch(relationship_type)
231  {
233  {
234  relationships.insert(std::make_pair(IR_LOWERING, SAME_FUNCTION));
235  break;
236  }
239  {
240  break;
241  }
242  default:
243  THROW_UNREACHABLE("");
244  }
245  return relationships;
246 }
247 
249 
251 {
252  if(opSSA->get_kind() == integer_cst_K)
253  {
254  return tree_nodeRef();
255  }
256  THROW_ASSERT(opSSA->get_kind() == ssa_name_K, "unexpected condition:" + opSSA->ToString());
257  auto* ssa_opSSA = GetPointerS<ssa_name>(opSSA);
258  auto opSSA_def_stmt = GET_NODE(ssa_opSSA->CGetDefStmt());
259  if(opSSA_def_stmt->get_kind() == gimple_nop_K || opSSA_def_stmt->get_kind() == gimple_phi_K)
260  {
261  return tree_nodeRef();
262  }
263  THROW_ASSERT(opSSA_def_stmt->get_kind() == gimple_assign_K,
264  "unexpected condition: " + opSSA_def_stmt->get_kind_text());
265  auto* opSSA_assign = GetPointerS<gimple_assign>(opSSA_def_stmt);
266  return GET_NODE(opSSA_assign->op1);
267 }
268 
269 static bool varFound(tree_nodeRef node, unsigned& vd_index, tree_nodeRef& vd_node)
270 {
271  THROW_ASSERT(node->get_kind() == addr_expr_K, "unexpected condition");
272  auto* ae = GetPointerS<addr_expr>(node);
273  auto ae_op = GET_NODE(ae->op);
274  if(ae_op->get_kind() == parm_decl_K)
275  {
276  return false;
277  }
278  THROW_ASSERT(ae_op->get_kind() == var_decl_K, "unexpected condition: " + ae_op->get_kind_text());
279  vd_index = GET_INDEX_NODE(ae->op);
280  vd_node = ae->op;
281  return true;
282 }
283 
284 #define REBUILD2_DEVEL 0
285 #if REBUILD2_DEVEL
286 #define unexpetedPattern(node) \
287  THROW_ERROR("unexpected condition: " + node->get_kind_text() + " --- " + node->ToString());
288 #else
290 {
291  return false;
292 }
293 #endif
294 
295 bool rebuild_initialization2::extract_var_decl_ppe(tree_nodeRef addr_assign_op1, unsigned& vd_index,
296  tree_nodeRef& vd_node)
297 {
298  auto* ppe = GetPointerS<pointer_plus_expr>(addr_assign_op1);
299  auto ppe_op0 = GET_NODE(ppe->op0);
300  auto addr2_assign_op1 = extractOp1(ppe_op0);
301  if(!addr2_assign_op1)
302  {
303  return false;
304  }
305  if(addr2_assign_op1->get_kind() == view_convert_expr_K || addr2_assign_op1->get_kind() == nop_expr_K)
306  {
307  auto* ue = GetPointerS<unary_expr>(addr2_assign_op1);
308  auto ue_op = GET_NODE(ue->op);
309  auto addr3_assign_op1 = extractOp1(ue_op);
310  if(!addr3_assign_op1)
311  {
312  return false;
313  }
314  if(addr3_assign_op1->get_kind() == addr_expr_K)
315  {
316  return varFound(addr3_assign_op1, vd_index, vd_node);
317  }
318  else if(GET_NODE(ppe->op1)->get_kind() == integer_cst_K && tree_helper::GetConstValue(ppe->op1) == 0)
319  {
320  if(addr3_assign_op1->get_kind() == ssa_name_K)
321  {
322  auto addr4_assign_op1 = extractOp1(addr3_assign_op1);
323  if(!addr4_assign_op1)
324  {
325  return false;
326  }
327  if(addr4_assign_op1->get_kind() == pointer_plus_expr_K)
328  {
329  addr_assign_op1 = addr4_assign_op1;
330  return extract_var_decl_ppe(addr_assign_op1, vd_index, vd_node);
331  }
332  else if(addr4_assign_op1->get_kind() == addr_expr_K)
333  {
334  return varFound(addr4_assign_op1, vd_index, vd_node);
335  }
336  else if(addr4_assign_op1->get_kind() == ssa_name_K)
337  {
338  auto addr5_assign_op1 = extractOp1(addr4_assign_op1);
339  if(!addr5_assign_op1)
340  {
341  return false;
342  }
343  if(addr5_assign_op1->get_kind() == pointer_plus_expr_K)
344  {
345  addr_assign_op1 = addr5_assign_op1;
346  return extract_var_decl_ppe(addr_assign_op1, vd_index, vd_node);
347  }
348  else
349  {
350  return unexpetedPattern(addr5_assign_op1);
351  }
352  }
353  else if(addr4_assign_op1->get_kind() == mem_ref_K)
354  {
355  return false;
356  }
357  else
358  {
359  return unexpetedPattern(addr4_assign_op1);
360  }
361  }
362  else if(addr3_assign_op1->get_kind() == pointer_plus_expr_K)
363  {
364  addr_assign_op1 = addr3_assign_op1;
365  return extract_var_decl_ppe(addr_assign_op1, vd_index, vd_node);
366  }
367  else
368  {
369  return unexpetedPattern(addr3_assign_op1);
370  }
371  }
372  else if(addr3_assign_op1->get_kind() == ssa_name_K)
373  {
374  auto addr4_assign_op1 = extractOp1(addr3_assign_op1);
375  if(!addr4_assign_op1)
376  {
377  return false;
378  }
379  if(addr4_assign_op1->get_kind() == addr_expr_K)
380  {
381  return varFound(addr4_assign_op1, vd_index, vd_node);
382  }
383  else if(addr4_assign_op1->get_kind() == ssa_name_K)
384  {
385  auto addr5_assign_op1 = extractOp1(addr4_assign_op1);
386  if(!addr5_assign_op1)
387  {
388  return false;
389  }
390  return unexpetedPattern(addr5_assign_op1);
391  }
392  else if(addr4_assign_op1->get_kind() == nop_expr_K)
393  {
394  auto* ne1 = GetPointerS<nop_expr>(addr4_assign_op1);
395  auto ne1_op = GET_NODE(ne1->op);
396  auto addr5_assign_op1 = extractOp1(ne1_op);
397  if(!addr5_assign_op1)
398  {
399  return false;
400  }
401  return unexpetedPattern(addr5_assign_op1);
402  }
403  else if(addr4_assign_op1->get_kind() == pointer_plus_expr_K)
404  {
405  return false;
406  }
407  else
408  {
409  return unexpetedPattern(addr4_assign_op1);
410  }
411  }
412  else if(addr3_assign_op1->get_kind() == view_convert_expr_K)
413  {
414  auto* ue1 = GetPointerS<unary_expr>(addr3_assign_op1);
415  auto ue1_op = GET_NODE(ue1->op);
416  if(ue1_op->get_kind() == ssa_name_K)
417  {
418  auto addr4_assign_op1 = extractOp1(ue1_op);
419  if(!addr4_assign_op1)
420  {
421  return false;
422  }
423  if(addr4_assign_op1->get_kind() == addr_expr_K)
424  {
425  return varFound(addr4_assign_op1, vd_index, vd_node);
426  }
427  else if(addr4_assign_op1->get_kind() == pointer_plus_expr_K)
428  {
429  return false;
430  }
431  else
432  {
433  return unexpetedPattern(addr4_assign_op1);
434  }
435  }
436  else
437  {
438  return unexpetedPattern(ue1_op);
439  }
440  }
441  else if(addr3_assign_op1->get_kind() == pointer_plus_expr_K)
442  {
443  return false;
444  }
445  else if(addr3_assign_op1->get_kind() == plus_expr_K)
446  {
447  return false;
448  }
449  else if(addr3_assign_op1->get_kind() == call_expr_K)
450  {
451  return false;
452  }
453  else
454  {
455  return unexpetedPattern(addr3_assign_op1);
456  }
457  }
458  else if(addr2_assign_op1->get_kind() == addr_expr_K)
459  {
460  return varFound(addr2_assign_op1, vd_index, vd_node);
461  }
462  else if(addr2_assign_op1->get_kind() == ssa_name_K)
463  {
464  auto addr3_assign_op1 = extractOp1(addr2_assign_op1);
465  if(!addr3_assign_op1)
466  {
467  return false;
468  }
469  if(addr3_assign_op1->get_kind() == pointer_plus_expr_K)
470  {
471  if(GET_NODE(ppe->op1)->get_kind() == integer_cst_K && tree_helper::GetConstValue(ppe->op1) == 0)
472  {
473  addr_assign_op1 = addr3_assign_op1;
474  return extract_var_decl_ppe(addr_assign_op1, vd_index, vd_node);
475  }
476  else
477  {
478  return false;
479  }
480  }
481  else if(addr3_assign_op1->get_kind() == addr_expr_K)
482  {
483  return varFound(addr3_assign_op1, vd_index, vd_node);
484  }
485  else
486  {
487  return unexpetedPattern(addr3_assign_op1);
488  }
489  }
490  else if(addr2_assign_op1->get_kind() == pointer_plus_expr_K)
491  {
492  return false;
493  }
494  else if(addr2_assign_op1->get_kind() == mem_ref_K)
495  {
496  return false;
497  }
498  else if(addr2_assign_op1->get_kind() == call_expr_K)
499  {
500  return false;
501  }
502  else if(addr2_assign_op1->get_kind() == cond_expr_K)
503  {
504  return false;
505  }
506  else
507  {
508  return unexpetedPattern(addr2_assign_op1);
509  }
510 }
511 
512 bool rebuild_initialization2::extract_var_decl(const mem_ref* me, unsigned& vd_index, tree_nodeRef& vd_node,
513  tree_nodeRef& addr_assign_op1)
514 {
515  auto me_op1 = GET_NODE(me->op1);
516  THROW_ASSERT(me_op1->get_kind() == integer_cst_K, "unexpected condition");
517  THROW_ASSERT(tree_helper::GetConstValue(me->op1) == 0, "unexpected condition");
518  auto me_op0 = GET_NODE(me->op0);
519  addr_assign_op1 = extractOp1(me_op0);
520  if(!addr_assign_op1)
521  {
522  return false;
523  }
524  if(addr_assign_op1->get_kind() == pointer_plus_expr_K)
525  {
526  return extract_var_decl_ppe(addr_assign_op1, vd_index, vd_node);
527  }
528  else if(addr_assign_op1->get_kind() == ssa_name_K)
529  {
530  auto addr2_assign_op1 = extractOp1(addr_assign_op1);
531  if(!addr2_assign_op1)
532  {
533  return false;
534  }
535  if(addr2_assign_op1->get_kind() == nop_expr_K)
536  {
537  auto* ne = GetPointerS<nop_expr>(addr2_assign_op1);
538  auto ne_op = GET_NODE(ne->op);
539  auto addr3_assign_op1 = extractOp1(ne_op);
540  if(!addr3_assign_op1)
541  {
542  return false;
543  }
544  return unexpetedPattern(addr3_assign_op1);
545  }
546  else if(addr2_assign_op1->get_kind() == pointer_plus_expr_K)
547  {
548  addr_assign_op1 = addr2_assign_op1;
549  return extract_var_decl_ppe(addr_assign_op1, vd_index, vd_node);
550  }
551  else if(addr2_assign_op1->get_kind() == addr_expr_K)
552  {
553  return varFound(addr2_assign_op1, vd_index, vd_node);
554  }
555  else if(addr2_assign_op1->get_kind() == mem_ref_K)
556  {
557  return false;
558  }
559  else
560  {
561  return unexpetedPattern(addr2_assign_op1);
562  }
563  }
564  else if(addr_assign_op1->get_kind() == addr_expr_K)
565  {
566  return varFound(addr_assign_op1, vd_index, vd_node);
567  }
568  else if(addr_assign_op1->get_kind() == view_convert_expr_K || addr_assign_op1->get_kind() == nop_expr_K ||
569  addr_assign_op1->get_kind() == convert_expr_K)
570  {
571  auto* ue = GetPointerS<unary_expr>(addr_assign_op1);
572  auto ue_op = GET_NODE(ue->op);
573  auto addr1_assign_op1 = extractOp1(ue_op);
574  if(!addr1_assign_op1)
575  {
576  return false;
577  }
578  if(addr1_assign_op1->get_kind() == addr_expr_K)
579  {
580  return varFound(addr1_assign_op1, vd_index, vd_node);
581  }
582  else if(addr1_assign_op1->get_kind() == ssa_name_K)
583  {
584  auto addr2_assign_op1 = extractOp1(addr1_assign_op1);
585  if(!addr2_assign_op1)
586  {
587  return false;
588  }
589  if(addr2_assign_op1->get_kind() == pointer_plus_expr_K)
590  {
591  addr_assign_op1 = addr2_assign_op1;
592  return extract_var_decl_ppe(addr_assign_op1, vd_index, vd_node);
593  }
594  return unexpetedPattern(addr2_assign_op1);
595  }
596  else if(addr1_assign_op1->get_kind() == nop_expr_K)
597  {
598  auto* ne1 = GetPointerS<unary_expr>(addr1_assign_op1);
599  auto ne1_op = GET_NODE(ne1->op);
600  auto addr2_assign_op1 = extractOp1(ne1_op);
601  if(!addr2_assign_op1)
602  {
603  return false;
604  }
605  if(addr2_assign_op1->get_kind() == ssa_name_K)
606  {
607  auto addr3_assign_op1 = extractOp1(ne1_op);
608  if(!addr3_assign_op1)
609  {
610  return false;
611  }
612  if(addr3_assign_op1->get_kind() == pointer_plus_expr_K)
613  {
614  addr_assign_op1 = addr3_assign_op1;
615  return extract_var_decl_ppe(addr_assign_op1, vd_index, vd_node);
616  }
617  else
618  {
619  return unexpetedPattern(addr3_assign_op1);
620  }
621  }
622  else
623  {
624  return unexpetedPattern(addr2_assign_op1);
625  }
626  }
627  else if(addr1_assign_op1->get_kind() == pointer_plus_expr_K)
628  {
629  addr_assign_op1 = addr1_assign_op1;
630  return extract_var_decl_ppe(addr_assign_op1, vd_index, vd_node);
631  }
632  else
633  {
634  return unexpetedPattern(addr1_assign_op1);
635  }
636  }
637  else if(addr_assign_op1->get_kind() == mem_ref_K)
638  {
639  return false;
640  }
641  else if(addr_assign_op1->get_kind() == call_expr_K)
642  {
643  return false;
644  }
645  else if(addr_assign_op1->get_kind() == cond_expr_K)
646  {
647  return false;
648  }
649  else
650  {
651  return unexpetedPattern(addr_assign_op1);
652  }
653 }
654 
655 #define foundNonConstant(VD) \
656  do \
657  { \
658  nonConstantVars.insert(VD); \
659  auto key = TM->CGetTreeReindex(VD); \
660  inits.erase(key); \
661  } while(0)
662 
663 #if REBUILD2_DEVEL
664 #define unexpetedPattern2(node, VD) \
665  THROW_ERROR("unexpected condition: " + node->get_kind_text() + " --- " + node->ToString());
666 #else
667 #define unexpetedPattern2(node, VD) foundNonConstant(VD)
668 #endif
669 
670 tree_nodeRef getAssign(tree_nodeRef SSAop, unsigned vd_index, CustomOrderedSet<unsigned>& nonConstantVars,
671  TreeNodeMap<std::map<integer_cst_t, tree_nodeRef>>& inits, tree_managerRef TM)
672 {
673  THROW_ASSERT(SSAop->get_kind() == ssa_name_K, "unexpected condition");
674  auto* ssa_var = GetPointerS<ssa_name>(SSAop);
675  auto ssa_def_stmt = GET_NODE(ssa_var->CGetDefStmt());
676  if(ssa_def_stmt->get_kind() == gimple_nop_K || ssa_def_stmt->get_kind() == gimple_phi_K)
677  {
678  nonConstantVars.insert(vd_index);
679  auto key = TM->CGetTreeReindex(vd_index);
680  inits.erase(key);
681  return tree_nodeRef();
682  }
683  else
684  {
685  THROW_ASSERT(ssa_def_stmt->get_kind() == gimple_assign_K,
686  "unexpected condition: " + ssa_def_stmt->get_kind_text());
687  auto* assign = GetPointerS<gimple_assign>(ssa_def_stmt);
688  return GET_NODE(assign->op1);
689  }
690 }
691 
693 {
694  tree_managerRef TM = AppM->get_tree_manager();
697  auto* fd = GetPointerS<function_decl>(tn);
698  THROW_ASSERT(fd && fd->body, "Node is not a function or it hasn't a body");
699  auto* sl = GetPointerS<statement_list>(GET_NODE(fd->body));
700  THROW_ASSERT(sl, "Body is not a statement_list");
701  bool not_supported = false;
702  std::map<unsigned, unsigned> var_writing_BB_relation;
703  std::map<unsigned, unsigned long long> var_writing_size_relation;
704  std::map<unsigned, unsigned long long> var_writing_elts_size_relation;
705  CustomOrderedSet<unsigned> nonConstantVars;
707 
709  for(const auto& Bit : sl->list_of_bloc)
710  {
711  // used to collect the reads of a given variable done in the same basic block.
712  // This is done to avoid to classify a variable constant in case is first
713  // written the read and then written again.
714  CustomOrderedSet<unsigned> VarsReadSeen;
715  auto B = Bit.second;
716  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining for write BB" + STR(B->number));
717  const auto& list_of_stmt = B->CGetStmtList();
718  for(const auto& inst : list_of_stmt)
719  {
720  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining statement " + GET_NODE(inst)->ToString());
721  auto gn = GetPointerS<gimple_node>(GET_NODE(inst));
722  auto stmt_kind = GET_NODE(inst)->get_kind();
723  if(gn->vdef && stmt_kind != gimple_assign_K)
724  {
725  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined statement: pattern not supported");
726  not_supported = true;
727  break;
728  }
729  if(stmt_kind == gimple_assign_K && gn->vdef)
730  {
731  auto ga = GetPointerS<gimple_assign>(GET_NODE(inst));
732  auto op0 = GET_NODE(ga->op0);
733  auto op1 = GET_NODE(ga->op1);
734  if(op0->get_kind() == mem_ref_K)
735  {
736  unsigned vd_index = 0;
737  tree_nodeRef vd_node;
738  tree_nodeRef addr_assign_op1;
739  auto* me = GetPointerS<mem_ref>(op0);
740  auto resolved = extract_var_decl(me, vd_index, vd_node, addr_assign_op1);
741  if(resolved && nonConstantVars.find(vd_index) == nonConstantVars.end())
742  {
743  THROW_ASSERT(vd_index && vd_node, "unexpected condition");
745  "---variable written: " + TM->get_tree_node_const(vd_index)->ToString());
747  if(!GetPointer<cst_node>(op1))
748  {
750  "---variable is not constant(1): " + TM->get_tree_node_const(vd_index)->ToString());
751  foundNonConstant(vd_index);
752  }
753  if(nonConstantVars.find(vd_index) == nonConstantVars.end())
754  {
755  if(VarsReadSeen.find(vd_index) != VarsReadSeen.end())
756  {
758  "---variable is not constant(2): " +
759  TM->get_tree_node_const(vd_index)->ToString());
760  foundNonConstant(vd_index);
761  }
762  else if(var_writing_BB_relation.find(vd_index) == var_writing_BB_relation.end())
763  {
765  auto* vd = GetPointerS<var_decl>(GET_NODE(vd_node));
766  if(vd->init)
767  {
769  "---variable is initialized: " +
770  TM->get_tree_node_const(vd_index)->ToString());
771  foundNonConstant(vd_index);
772  }
773  else if(not vd->scpe or GET_NODE(vd->scpe)->get_kind() == translation_unit_decl_K)
774  {
776  "---variable is not local: " + TM->get_tree_node_const(vd_index)->ToString());
777  foundNonConstant(vd_index);
778  }
779  else
780  {
781  auto Type = GET_CONST_NODE(vd->type);
783  if(Type->get_kind() == array_type_K)
784  {
785  std::vector<unsigned long long> dims;
786  unsigned long long elts_size;
787  auto type_index = tree_helper::CGetType(vd_node)->index;
788  tree_helper::get_array_dim_and_bitsize(TM, type_index, dims, elts_size);
789  if(dims.size() == 1)
790  {
792  var_writing_BB_relation[vd_index] = B->number;
793  var_writing_size_relation[vd_index] = dims[0];
794  var_writing_elts_size_relation[vd_index] = elts_size;
795  }
796  else
797  {
799  "---variable is not constant(3): " +
800  TM->get_tree_node_const(vd_index)->ToString());
801  foundNonConstant(vd_index);
802  }
803  }
804  else
805  {
807  "---variable is currently classified as non-constant: " +
808  TM->get_tree_node_const(vd_index)->ToString());
809  foundNonConstant(vd_index);
810  }
811  }
812  }
813  else if(var_writing_BB_relation.find(vd_index)->second != B->number)
814  {
816  "---variable is not constant(4): " +
817  TM->get_tree_node_const(vd_index)->ToString());
818  foundNonConstant(vd_index);
819  }
821  if(nonConstantVars.find(vd_index) == nonConstantVars.end())
822  {
824  if(addr_assign_op1->get_kind() == pointer_plus_expr_K)
825  {
826  auto* ppe = GetPointerS<pointer_plus_expr>(addr_assign_op1);
827  auto ppe_op1 = GET_NODE(ppe->op1);
828  if(ppe_op1->get_kind() == ssa_name_K)
829  {
830  auto offset_assign_op1 = getAssign(ppe_op1, vd_index, nonConstantVars, inits, TM);
831  if(!offset_assign_op1)
832  {
834  "---variable is not constant(9): " +
835  TM->get_tree_node_const(vd_index)->ToString());
836  }
837  else
838  {
839  if(offset_assign_op1->get_kind() == lshift_expr_K)
840  {
841  auto* ls = GetPointerS<lshift_expr>(offset_assign_op1);
842  auto ls_op1 = GET_NODE(ls->op1);
843  if(ls_op1->get_kind() == integer_cst_K)
844  {
845  THROW_ASSERT(tree_helper::GetConstValue(ls->op1) >= 0, "");
846  auto nbit = static_cast<unsigned long long>(tree_helper::GetConstValue(ls->op1));
847  THROW_ASSERT(nbit < 32, "unexpected condition");
848  std::vector<unsigned long long> dims;
849  THROW_ASSERT(var_writing_elts_size_relation.find(vd_index) !=
850  var_writing_elts_size_relation.end(),
851  "unexpected condition");
852  auto elts_size = var_writing_elts_size_relation[vd_index];
853  if(elts_size != (8ULL << nbit))
854  {
856  "---variable is not constant(9c): " +
857  TM->get_tree_node_const(vd_index)->ToString());
858  foundNonConstant(vd_index);
859  }
860  else
861  {
862  auto ls_op0 = GET_NODE(ls->op0);
863  if(ls_op0->get_kind() == ssa_name_K)
864  {
865  auto nop_assign_op1 =
866  getAssign(ls_op0, vd_index, nonConstantVars, inits, TM);
867  if(!nop_assign_op1)
868  {
870  "---variable is not constant(9): " +
871  TM->get_tree_node_const(vd_index)->ToString());
872  }
873  else
874  {
875  if(nop_assign_op1->get_kind() == nop_expr_K)
876  {
877  auto* ne = GetPointerS<nop_expr>(nop_assign_op1);
878  auto ne_op = GET_NODE(ne->op);
879  if(ne_op->get_kind() == integer_cst_K)
880  {
882  inits[vd_node][tree_helper::GetConstValue(ne->op)] = ga->op1;
883  }
884  else
885  {
887  "---variable is not constant(5a): " +
888  TM->get_tree_node_const(vd_index)->ToString());
889  foundNonConstant(vd_index);
890  }
891  }
892  else if(nop_assign_op1->get_kind() == integer_cst_K)
893  {
895  inits[vd_node][tree_helper::GetConstValue(nop_assign_op1)] = ga->op1;
896  }
897  else if(nop_assign_op1->get_kind() != view_convert_expr_K)
898  {
900  "---variable is not constant(5b): " +
901  TM->get_tree_node_const(vd_index)->ToString());
902  foundNonConstant(vd_index);
903  }
904  else
905  {
906  unexpetedPattern2(nop_assign_op1, vd_index);
907  }
908  }
909  }
910  else
911  {
912  unexpetedPattern2(ls_op0, vd_index);
913  }
914  }
915  }
916  else
917  {
918  unexpetedPattern2(ls_op1, vd_index);
919  }
920  }
921  else if(offset_assign_op1->get_kind() == ssa_name_K)
922  {
923  auto offset_assign1_op1 =
924  getAssign(offset_assign_op1, vd_index, nonConstantVars, inits, TM);
925  if(!offset_assign1_op1)
926  {
928  "---variable is not constant(9): " +
929  TM->get_tree_node_const(vd_index)->ToString());
930  }
931  else
932  {
933  if(offset_assign1_op1->get_kind() == nop_expr_K)
934  {
935  auto* ne = GetPointerS<nop_expr>(offset_assign1_op1);
936  auto ne_op = GET_NODE(ne->op);
937  if(ne_op->get_kind() == integer_cst_K)
938  {
939  inits[vd_node][tree_helper::GetConstValue(ne->op)] = ga->op1;
940  }
941  else if(ne_op->get_kind() == ssa_name_K)
942  {
943  auto offset_assign2_op1 =
944  getAssign(ne_op, vd_index, nonConstantVars, inits, TM);
945  if(!offset_assign2_op1)
946  {
948  "---variable is not constant(5c): " +
949  TM->get_tree_node_const(vd_index)->ToString());
950  }
951  else if(offset_assign2_op1->get_kind() == integer_cst_K)
952  {
953  inits[vd_node][tree_helper::GetConstValue(offset_assign2_op1)] =
954  ga->op1;
955  }
956  else
957  {
959  "---variable is not constant(5c): " +
960  TM->get_tree_node_const(vd_index)->ToString());
961  foundNonConstant(vd_index);
962  }
963  }
964  else
965  {
966  unexpetedPattern2(ne_op, vd_index);
967  }
968  }
969  else
970  {
971  unexpetedPattern2(offset_assign1_op1, vd_index);
972  }
973  }
974  }
975  else if(offset_assign_op1->get_kind() == nop_expr_K)
976  {
977  auto* ne = GetPointerS<nop_expr>(offset_assign_op1);
978  auto ne_op = GET_NODE(ne->op);
979  if(ne_op->get_kind() == ssa_name_K)
980  {
981  auto offset_assign3_op1 = getAssign(ne_op, vd_index, nonConstantVars, inits, TM);
982  if(!offset_assign3_op1)
983  {
985  "---variable is not constant(9): " +
986  TM->get_tree_node_const(vd_index)->ToString());
987  }
988  else
989  {
990  unexpetedPattern2(offset_assign3_op1, vd_index);
991  }
992  }
993  else
994  {
995  unexpetedPattern2(ne_op, vd_index);
996  }
997  }
998  else
999  {
1000  unexpetedPattern2(offset_assign_op1, vd_index);
1001  }
1002  }
1003  }
1004  else if(ppe_op1->get_kind() == integer_cst_K)
1005  {
1006  THROW_ASSERT(var_writing_elts_size_relation.find(vd_index) !=
1007  var_writing_elts_size_relation.end(),
1008  "unexpected condition");
1009  inits[vd_node]
1010  [tree_helper::GetConstValue(ppe_op1) /
1011  (static_cast<integer_cst_t>(var_writing_elts_size_relation[vd_index]) / 8)] =
1012  ga->op1;
1013  }
1014  else
1015  {
1016  unexpetedPattern2(ppe_op1, vd_index);
1017  }
1018  }
1019  else if(addr_assign_op1->get_kind() == view_convert_expr_K)
1020  {
1021  inits[vd_node][0] = ga->op1;
1022  }
1023  else if(addr_assign_op1->get_kind() == ssa_name_K)
1024  {
1025  inits[vd_node][0] = ga->op1;
1026  }
1027  else if(addr_assign_op1->get_kind() == addr_expr_K)
1028  {
1029  inits[vd_node][0] = ga->op1;
1030  }
1031  else
1032  {
1033  unexpetedPattern2(addr_assign_op1, vd_index);
1034  }
1035  }
1036  }
1038  }
1039  else
1040  {
1042  "<--Examined statement: pattern not supported");
1043  not_supported = true;
1044  break;
1045  }
1046  }
1047  else if(op0->get_kind() == ssa_name_K && op1->get_kind() == call_expr_K)
1048  {
1049  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined statement: IPA is required");
1050  not_supported = true;
1051  break;
1052  }
1053  else if(op0->get_kind() == realpart_expr_K || op0->get_kind() == imagpart_expr_K)
1054  {
1055  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined statement: Not supported");
1056  not_supported = true;
1057  break;
1058  }
1059  else if(op0->get_kind() == ssa_name_K && op1->get_kind() == mem_ref_K)
1060  {
1061  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined statement: Not supported");
1062  not_supported = true;
1063  break;
1064  }
1065  else
1066  {
1068  "<--Examined statement: Not supported" + op0->get_kind_text());
1069  not_supported = true;
1070  break;
1071  }
1072  }
1073  else if(stmt_kind == gimple_assign_K && !gn->vuses.empty())
1074  {
1075  auto ga = GetPointerS<gimple_assign>(GET_NODE(inst));
1076  auto op1 = GET_NODE(ga->op1);
1077  if(op1->get_kind() == mem_ref_K)
1078  {
1079  unsigned vd_index = 0;
1080  tree_nodeRef vd_node;
1081  tree_nodeRef dummy_var;
1082  auto* me = GetPointerS<mem_ref>(op1);
1083  auto resolved = extract_var_decl(me, vd_index, vd_node, dummy_var);
1084  if(resolved)
1085  {
1087  "---variable read: " + TM->CGetTreeNode(vd_index)->ToString());
1088  VarsReadSeen.insert(vd_index);
1089  }
1090  else
1091  {
1093  "<--Examined statement: pattern not supported");
1094  not_supported = true;
1095  break;
1096  }
1097  }
1098  else
1099  {
1100  for(auto var_written : var_writing_BB_relation)
1101  {
1102  if(var_written.second == B->number)
1103  {
1104  VarsReadSeen.insert(var_written.first);
1105  }
1106  }
1107  }
1108  }
1109  else if(!gn->vuses.empty())
1110  {
1111  for(auto var_written : var_writing_BB_relation)
1112  {
1113  if(var_written.second == B->number)
1114  {
1115  VarsReadSeen.insert(var_written.first);
1116  }
1117  }
1118  }
1119  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined statement");
1120  }
1121  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined for write BB" + STR(B->number));
1122  if(not_supported)
1123  {
1124  break;
1125  }
1126  }
1127  if(not_supported || var_writing_BB_relation.empty() ||
1128  var_writing_BB_relation.size() == static_cast<size_t>(nonConstantVars.size()))
1129  {
1130  return false;
1131  }
1132 
1134  BBGraphsCollectionRef GCC_bb_graphs_collection(
1136  BBGraphRef GCC_bb_graph(new BBGraph(GCC_bb_graphs_collection, CFG_SELECTOR));
1137  CustomUnorderedMap<unsigned int, vertex> inverse_vertex_map;
1139  for(const auto& block : sl->list_of_bloc)
1140  {
1141  inverse_vertex_map[block.first] =
1142  GCC_bb_graphs_collection->AddVertex(BBNodeInfoRef(new BBNodeInfo(block.second)));
1143  }
1145  for(const auto& curr_bb_pair : sl->list_of_bloc)
1146  {
1147  auto curr_bb = curr_bb_pair.first;
1148  auto lop_it_end = sl->list_of_bloc[curr_bb]->list_of_pred.end();
1149  for(auto lop_it = sl->list_of_bloc[curr_bb]->list_of_pred.begin(); lop_it != lop_it_end; ++lop_it)
1150  {
1151  THROW_ASSERT(inverse_vertex_map.find(*lop_it) != inverse_vertex_map.end(),
1152  "BB" + STR(*lop_it) + " (successor of BB" + STR(curr_bb) + ") does not exist");
1153  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[*lop_it], inverse_vertex_map[curr_bb], CFG_SELECTOR);
1154  }
1155  auto los_it_end = sl->list_of_bloc[curr_bb]->list_of_succ.end();
1156  for(auto los_it = sl->list_of_bloc[curr_bb]->list_of_succ.begin(); los_it != los_it_end; ++los_it)
1157  {
1158  if(*los_it == bloc::EXIT_BLOCK_ID)
1159  {
1160  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[curr_bb], inverse_vertex_map[*los_it], CFG_SELECTOR);
1161  }
1162  }
1163  if(sl->list_of_bloc[curr_bb]->list_of_succ.empty())
1164  {
1165  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[curr_bb], inverse_vertex_map[bloc::EXIT_BLOCK_ID],
1166  CFG_SELECTOR);
1167  }
1168  }
1170  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[bloc::ENTRY_BLOCK_ID], inverse_vertex_map[bloc::EXIT_BLOCK_ID],
1171  CFG_SELECTOR);
1172 
1174  for(const auto& Bit : sl->list_of_bloc)
1175  {
1176  auto B = Bit.second;
1177  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining for write BB" + STR(B->number));
1178  const auto& list_of_stmt = B->CGetStmtList();
1179  for(const auto& inst : list_of_stmt)
1180  {
1181  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining statement " + GET_NODE(inst)->ToString());
1182  auto gn = GetPointerS<gimple_node>(GET_NODE(inst));
1183  auto stmt_kind = GET_NODE(inst)->get_kind();
1184  if(stmt_kind == gimple_assign_K && !gn->vuses.empty())
1185  {
1186  auto ga = GetPointerS<gimple_assign>(GET_NODE(inst));
1187  auto op1 = GET_NODE(ga->op1);
1188  if(op1->get_kind() == mem_ref_K)
1189  {
1190  unsigned vd_index = 0;
1191  tree_nodeRef vd_node;
1192  tree_nodeRef dummy_var;
1193  auto* me = GetPointerS<mem_ref>(op1);
1194  auto resolved = extract_var_decl(me, vd_index, vd_node, dummy_var);
1195  if(resolved && nonConstantVars.find(vd_index) == nonConstantVars.end())
1196  {
1197  if(var_writing_BB_relation.find(vd_index) != var_writing_BB_relation.end())
1198  {
1199  auto BB_written = var_writing_BB_relation.find(vd_index)->second;
1200  if(GCC_bb_graph->IsReachable(inverse_vertex_map[BB_written], inverse_vertex_map[B->number]))
1201  {
1203  "---variable is not constant(6): " +
1204  TM->get_tree_node_const(vd_index)->ToString());
1205  foundNonConstant(vd_index);
1206  }
1207  }
1208  }
1209  else
1210  {
1211  THROW_ASSERT(resolved, "unexpected condition");
1212  }
1213  }
1214  else
1215  {
1216  for(auto var_written : var_writing_BB_relation)
1217  {
1218  if(nonConstantVars.find(var_written.first) == nonConstantVars.end())
1219  {
1220  auto BB_written = var_written.second;
1221  if(GCC_bb_graph->IsReachable(inverse_vertex_map[BB_written], inverse_vertex_map[B->number]))
1222  {
1224  "---variable is not constant(7): " +
1225  TM->CGetTreeNode(var_written.first)->ToString());
1226  foundNonConstant(var_written.first);
1227  }
1228  }
1229  }
1230  }
1231  }
1232  else if(!gn->vuses.empty())
1233  {
1234  for(auto var_written : var_writing_BB_relation)
1235  {
1236  if(nonConstantVars.find(var_written.first) == nonConstantVars.end())
1237  {
1238  auto BB_written = var_written.second;
1239  if(GCC_bb_graph->IsReachable(inverse_vertex_map[BB_written], inverse_vertex_map[B->number]))
1240  {
1242  "---variable is not constant(8): " +
1243  TM->CGetTreeNode(var_written.first)->ToString());
1244  foundNonConstant(var_written.first);
1245  }
1246  }
1247  }
1248  }
1249  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined statement");
1250  }
1251  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined for write BB" + STR(B->number));
1252  }
1253 
1255  CustomOrderedSet<unsigned> ConstantVars;
1256  for(auto vars : var_writing_BB_relation)
1257  {
1258  if(nonConstantVars.find(vars.first) == nonConstantVars.end())
1259  {
1260  auto key = TM->CGetTreeReindex(vars.first);
1261  auto initIt = inits.find(key);
1262  THROW_ASSERT(initIt != inits.end(), "unexpected condition");
1263  THROW_ASSERT(var_writing_size_relation.find(vars.first) != var_writing_size_relation.end(),
1264  "unexpected condition");
1265  if(initIt->second.size() == var_writing_size_relation.find(vars.first)->second)
1266  {
1267  auto vd_node = TM->get_tree_node_const(vars.first);
1268  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Constant variable: " + vd_node->ToString());
1269  ConstantVars.insert(vars.first);
1270  GetPointerS<var_decl>(vd_node)->readonly_flag = true;
1271  }
1272  else
1273  {
1274  inits.erase(initIt);
1275  }
1276  }
1277  }
1278  if(ConstantVars.empty())
1279  {
1280  return false;
1281  }
1282 
1283  for(const auto& Bit : sl->list_of_bloc)
1284  {
1285  auto B = Bit.second;
1286  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining for write BB" + STR(B->number));
1287  const auto& list_of_stmt = B->CGetStmtList();
1288  auto it_los_end = list_of_stmt.end();
1289  auto it_los = list_of_stmt.begin();
1290  while(it_los != it_los_end)
1291  {
1292  auto& inst = *it_los;
1293  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining statement " + GET_NODE(inst)->ToString());
1294  auto gn = GetPointerS<gimple_node>(GET_NODE(inst));
1295  auto stmt_kind = GET_NODE(inst)->get_kind();
1296  if(stmt_kind == gimple_assign_K && gn->vdef)
1297  {
1298  auto ga = GetPointerS<gimple_assign>(GET_NODE(inst));
1299  auto op0 = GET_NODE(ga->op0);
1300  if(op0->get_kind() == mem_ref_K)
1301  {
1302  unsigned vd_index = 0;
1303  tree_nodeRef vd_node;
1304  tree_nodeRef dummy_var;
1305  auto* me = GetPointerS<mem_ref>(op0);
1306  auto resolved = extract_var_decl(me, vd_index, vd_node, dummy_var);
1307  if(resolved && ConstantVars.find(vd_index) != ConstantVars.end())
1308  {
1309  if(ga->memdef)
1310  {
1311  const auto gimple_nop_id = TM->new_tree_node_id();
1312  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> gimple_nop_schema;
1313  gimple_nop_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
1314  gimple_nop_schema[TOK(TOK_SCPE)] = STR(function_id);
1315  TM->create_tree_node(gimple_nop_id, gimple_nop_K, gimple_nop_schema);
1316  GetPointerS<ssa_name>(GET_NODE(ga->memdef))->SetDefStmt(TM->GetTreeReindex(gimple_nop_id));
1317  }
1318  if(ga->vdef)
1319  {
1320  const auto gimple_nop_id = TM->new_tree_node_id();
1321  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> gimple_nop_schema;
1322  gimple_nop_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
1323  gimple_nop_schema[TOK(TOK_SCPE)] = STR(function_id);
1324  TM->create_tree_node(gimple_nop_id, gimple_nop_K, gimple_nop_schema);
1325  GetPointerS<ssa_name>(GET_NODE(ga->vdef))->SetDefStmt(TM->GetTreeReindex(gimple_nop_id));
1326  }
1327  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Removing " + STR(*it_los));
1328  B->RemoveStmt(*it_los, AppM);
1329  it_los = list_of_stmt.begin();
1330  it_los_end = list_of_stmt.end();
1331  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined statement");
1332  continue;
1333  }
1334  }
1335  }
1336  ++it_los;
1337  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined statement");
1338  }
1339  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined for write BB" + STR(B->number));
1340  }
1341  const auto behavioral_helper = function_behavior->CGetBehavioralHelper();
1342  const auto integer_type = tree_man->GetSignedIntegerType();
1343  for(const auto& init : inits)
1344  {
1345  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Rebuilding init of " + STR(init.first));
1346  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> constructor_tree_node_schema;
1347  const auto array_type = tree_helper::CGetType(init.first);
1348  constructor_tree_node_schema[TOK(TOK_TYPE)] = STR(array_type->index);
1350  const auto element_type = tree_helper::CGetElements(array_type);
1351  auto constructor_index = TM->new_tree_node_id();
1352  TM->create_tree_node(constructor_index, constructor_K, constructor_tree_node_schema);
1353  auto* constr = GetPointerS<constructor>(TM->GetTreeNode(constructor_index));
1354  const auto last_index = init.second.rbegin()->first;
1355  integer_cst_t index = 0;
1356  for(index = 0; index <= last_index; index++)
1357  {
1359  if(init.second.count(index))
1360  {
1361  constr->add_idx_valu(TM->CreateUniqueIntegerCst(index, integer_type), init.second.at(index));
1362  }
1363  else
1364  {
1365  THROW_ASSERT(GET_CONST_NODE(element_type)->get_kind() == integer_type_K,
1366  "Type not supported " + STR(element_type));
1367  const auto default_value = TM->CreateUniqueIntegerCst(0, element_type);
1368  constr->add_idx_valu(TM->CreateUniqueIntegerCst(index, integer_type), default_value);
1369  }
1370  }
1371  GetPointerS<var_decl>(GET_NODE(init.first))->init = TM->GetTreeReindex(constructor_index);
1372  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Rebuilt init of " + STR(init.first));
1373  }
1374 
1375  return true;
1376 }
1377 
1379 {
1380  bool modified = look_for_ROMs();
1381  if(modified)
1382  {
1383  function_behavior->UpdateBBVersion();
1384  }
1386 }
#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.
static bool unexpetedPattern(tree_nodeRef)
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
struct definition of the array_type tree node.
Definition: tree_node.hpp:1520
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.
Definition of the node_info object for the basic_block graph.
const tree_nodeRef CGetTreeReindex(const unsigned int i) const
Return a tree_reindex wrapping the i-th tree_node.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
~rebuild_initialization() override
Destructor.
rebuild_initialization2(const ParameterConstRef Param, const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
static tree_nodeConstRef CGetElements(const tree_nodeConstRef &type)
Given an array or a vector return the element type.
DesignFlowStep_Status InternalExec() override
Rebuild initialization function flow front-end step.
static bool varFound(tree_nodeRef node, unsigned &vd_index, tree_nodeRef &vd_node)
tree_nodeRef GetSignedIntegerType() const
Function that creates a integer type if it is not already present, otherwise it returns the one that ...
A simple interface to token object of the raw files.
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
#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
DesignFlowStep_Status InternalExec() override
Rebuild initialization function flow front-end step.
Data structure describing a basic block at tree level.
redefinition of map to manage ordered/unordered structures
#define TOK(token)
Macro used to convert a token symbol into a treeVocabularyTokenTypes.
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
#define unexpetedPattern2(node, VD)
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.
int key[32]
Definition: aes.h:67
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
bool extract_var_decl_ppe(tree_nodeRef addr_assign_op1, unsigned &vd_index, tree_nodeRef &vd_node)
extract_var_decl_ppe
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
Class used to describe a particular graph with basic blocks as nodes.
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
unsigned int new_tree_node_id(const unsigned int ask=0)
Return a new node id in the intermediate representation.
refcount< BBNodeInfo > BBNodeInfoRef
refcount definition of the class
Information associated with the whole basic-block graph.
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
void create_tree_node(const unsigned int node_id, enum kind tree_node_type, std::map< TreeVocabularyTokenTypes_TokenEnum, std::string > &tree_node_schema)
Factory method.
#define foundNonConstant(VD)
tree_nodeRef CreateUniqueIntegerCst(integer_cst_t value, const tree_nodeConstRef &type)
memoization of integer constants
#define index(x, y)
Definition: Keccak.c:74
kind
redefinition of set to manage ordered/unordered structures
tree_nodeRef GetTreeReindex(const unsigned int i)
Return a tree_reindex wrapping the i-th tree_node.
bool extract_var_decl(const mem_ref *me, unsigned &vd_index, tree_nodeRef &vd_node, tree_nodeRef &addr_assign_op1)
extract_var_decl return the variable decl referred by the mem_ref given it is resolvable ...
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
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.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
~rebuild_initialization2() override
Destructor.
rebuild_initialization(const ParameterConstRef Param, const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
This struct specifies the block node.
Definition: tree_node.hpp:1820
This file collects some utility functions.
tree_nodeRef GetTreeNode(const unsigned int index) const
Return the index-th tree_node (modifiable version)
Definition: APInt.hpp:53
void init(int bucket[BUCKETSIZE])
Definition: sort.c:42
bool IsReachable(const boost::graph_traits< graphs_collection >::vertex_descriptor x, const boost::graph_traits< graphs_collection >::vertex_descriptor y) const
Compute if vertex y is reachable from x.
Definition: graph.hpp:1004
#define BUILTIN_SRCP
const unsigned int function_id
The index of the function to be analyzed.
rebuild initialization where it is possible
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
tree_nodeRef getAssign(tree_nodeRef SSAop, unsigned vd_index, CustomOrderedSet< unsigned > &nonConstantVars, TreeNodeMap< std::map< integer_cst_t, tree_nodeRef >> &inits, tree_managerRef TM)
bool look_for_ROMs()
look_for_ROMs transforms the IR by looking for an initial sequence of writes followed by read only in...
Class specification of the basic_block structure.
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.
this class is used to manage the command-line or XML options.
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.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
Definition: tree_node.hpp:212
struct definition of the integer_type tree node.
Definition: tree_node.hpp:3279
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
static tree_nodeRef extractOp1(tree_nodeRef opSSA)
#define CFG_SELECTOR
Control flow graph edge selector.
#define B
Definition: generate.c:14
refcount< BBGraphInfo > BBGraphInfoRef
refcount definition of the class
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
Class specification of the manager of the tree structures extracted from the raw file.
A map with key tree_nodeRef.
Definition: tree_helper.hpp:65
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
static void get_array_dim_and_bitsize(const tree_managerConstRef &TM, const unsigned int index, std::vector< unsigned long long > &dims, unsigned long long &elts_bitsize)
Return the dimension of the array.
This structure defines graphs where nodes are basic_blocks.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

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