PandA-2024.02
tree_basic_block.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  */
44 #include "tree_basic_block.hpp"
45 
46 #include "application_manager.hpp"
47 #include "behavioral_helper.hpp"
48 #include "call_graph.hpp"
49 #include "call_graph_manager.hpp"
50 #include "function_behavior.hpp"
51 #include "op_graph.hpp"
52 #include "schedule.hpp"
53 #include "string_manipulation.hpp" // for STR
54 #include "tree_helper.hpp"
55 #include "tree_manager.hpp"
56 #include "tree_node.hpp"
57 #include "tree_reindex.hpp"
58 
59 const unsigned int bloc::ENTRY_BLOCK_ID = BB_ENTRY;
60 const unsigned int bloc::EXIT_BLOCK_ID = BB_EXIT;
61 
62 bloc::bloc(unsigned int _number)
63  : removed_phi(0), updated_ssa_uses(false), number(_number), loop_id(0), hpl(0), true_edge(0), false_edge(0)
64 {
65 }
66 
67 bloc::~bloc() = default;
68 
69 void bloc::visit(tree_node_visitor* const v) const
70 {
71  unsigned int mask = ALL_VISIT;
72  (*v)(this, mask);
76 }
77 
78 bool bloc::check_function_call(const tree_nodeRef& statement, gimple_assign* ga, unsigned int& called_function_id)
79 {
80  called_function_id = 0;
81  if(ga)
82  {
83  const auto ce = GetPointerS<const call_expr>(GET_NODE(ga->op1));
84  if(GET_NODE(ce->fn)->get_kind() == addr_expr_K)
85  {
86  const auto fn = GetPointerS<const addr_expr>(GET_CONST_NODE(ce->fn))->op;
87  if(GET_NODE(fn)->get_kind() == function_decl_K)
88  {
89  called_function_id = GET_INDEX_CONST_NODE(fn);
90  return true;
91  }
92  }
93  }
94  else
95  {
96  const auto gc = GetPointerS<gimple_call>(GET_NODE(statement));
97  if(GET_NODE(gc->fn)->get_kind() == addr_expr_K)
98  {
99  const auto fn = GetPointerS<const addr_expr>(GET_CONST_NODE(gc->fn))->op;
100  if(GET_NODE(fn)->get_kind() == function_decl_K)
101  {
102  called_function_id = GET_INDEX_NODE(fn);
103  return true;
104  }
105  }
106  }
107  return false;
108 }
109 
111 {
112  TreeNodeSet current_uses;
113  for(const auto& phi : list_of_phi)
114  {
115  auto gp = GetPointer<gimple_phi>(GET_NODE(phi));
116  current_uses.insert(gp->res);
117  }
118  std::list<tree_nodeRef> list_of_postponed_stmt;
119  auto pos = list_of_stmt.begin();
120  while(pos != list_of_stmt.end())
121  {
122  if(GET_NODE(*pos)->get_kind() == gimple_assign_K)
123  {
124  auto ga = GetPointer<gimple_assign>(GET_NODE(*pos));
125  if(GET_NODE(ga->op0)->get_kind() != ssa_name_K)
126  {
127  ++pos;
128  continue;
129  }
130  auto allDefinedP = [&](tree_nodeRef stmt) -> bool {
131  const auto& uses = tree_helper::ComputeSsaUses(stmt);
132  for(const auto& u : uses)
133  {
134  if(current_uses.find(u.first) == current_uses.end())
135  {
136  auto ssa_node = GET_NODE(u.first);
137  auto ssa = GetPointer<ssa_name>(ssa_node);
138  if(ssa->virtual_flag || GetPointer<gimple_node>(GET_NODE(ssa->CGetDefStmt()))->bb_index != number)
139  {
140  current_uses.insert(u.first);
141  }
142  else
143  {
144  return false;
145  }
146  }
147  }
148  return true;
149  };
150 
151  if(not allDefinedP(*pos))
152  {
153  list_of_postponed_stmt.push_back(*pos);
154  const auto next_stmt = std::next(pos);
155  list_of_stmt.erase(pos);
156  pos = next_stmt;
157  }
158  else
159  {
160  current_uses.insert(ga->op0);
161  const auto next_stmt = std::next(pos);
162  bool restart_postponed = false;
163  do
164  {
165  restart_postponed = false;
166  auto posPostponed = list_of_postponed_stmt.begin();
167  while(posPostponed != list_of_postponed_stmt.end())
168  {
169  if(allDefinedP(*posPostponed))
170  {
172  list_of_stmt.insert(next_stmt, *posPostponed);
173  auto gaPostponed = GetPointer<gimple_assign>(GET_NODE(*posPostponed));
174  current_uses.insert(gaPostponed->op0);
175  restart_postponed = true;
176  if(schedule)
177  {
178  schedule->UpdateTime(gaPostponed->index);
179  }
180  list_of_postponed_stmt.erase(posPostponed);
181  break;
182  }
183  else
184  {
185  ++posPostponed;
186  }
187  }
188  } while(restart_postponed);
189  pos = next_stmt;
190  }
191  }
192  else
193  {
194  ++pos;
195  }
196  }
197 }
198 
199 void bloc::manageCallGraph(const application_managerRef& AppM, const tree_nodeRef& statement)
200 {
201  const auto ga = GetPointer<gimple_assign>(GET_NODE(statement));
202  if((ga && (GET_NODE(ga->op1)->get_kind() == call_expr_K || GET_NODE(ga->op1)->get_kind() == aggr_init_expr_K)) ||
203  GET_NODE(statement)->get_kind() == gimple_call_K)
204  {
205  const auto cg_man = AppM->GetCallGraphManager();
206  THROW_ASSERT(cg_man, "");
207  THROW_ASSERT(GetPointerS<const gimple_node>(GET_NODE(statement))->scpe, "statement " + statement->ToString());
208  unsigned int called_function_id;
209  if(check_function_call(statement, ga, called_function_id))
210  {
211  const auto function_id = GET_INDEX_NODE(GetPointerS<const gimple_node>(GET_NODE(statement))->scpe);
212  if(cg_man->IsVertex(function_id))
213  {
214  CallGraphManager::addCallPointAndExpand(already_visited, AppM, function_id, called_function_id,
215  GET_INDEX_CONST_NODE(statement),
217  }
218  }
219  }
220 }
221 
223 {
225  if(GET_NODE(new_stmt))
226  {
227  if(AppM)
228  {
229  manageCallGraph(AppM, new_stmt);
230  }
231  const auto gn = GetPointer<gimple_node>(GET_NODE(new_stmt));
232  THROW_ASSERT(gn, "");
233  gn->bb_index = number;
234 
235  if(gn->vdef)
236  {
237  THROW_ASSERT(GET_NODE(gn->vdef)->get_kind() == ssa_name_K, "");
238  GetPointerS<ssa_name>(GET_NODE(gn->vdef))->SetDefStmt(new_stmt);
239  }
240 
241  if(gn->memdef)
242  {
243  THROW_ASSERT(GET_NODE(gn->memdef)->get_kind() == ssa_name_K, "");
244  GetPointerS<ssa_name>(GET_NODE(gn->memdef))->SetDefStmt(new_stmt);
245  }
246 
247  if(GET_NODE(new_stmt)->get_kind() == gimple_assign_K)
248  {
249  const auto ga = GetPointerS<gimple_assign>(GET_NODE(new_stmt));
250  if(GET_NODE(ga->op0) && GET_NODE(ga->op0)->get_kind() == ssa_name_K)
251  {
252  GetPointerS<ssa_name>(GET_NODE(ga->op0))->SetDefStmt(new_stmt);
253  }
254  }
255  else if(GET_NODE(new_stmt)->get_kind() == gimple_phi_K)
256  {
257  const auto gp = GetPointerS<gimple_phi>(GET_NODE(new_stmt));
258  if(GET_NODE(gp->res) && GET_NODE(gp->res)->get_kind() == ssa_name_K)
259  {
260  GetPointerS<ssa_name>(GET_NODE(gp->res))->SetDefStmt(new_stmt);
261  }
262  }
263 
264  if(updated_ssa_uses)
265  {
266  const auto& uses = tree_helper::ComputeSsaUses(new_stmt);
267  for(const auto& use : uses)
268  {
269  for(size_t counter = 0; counter < use.second; counter++)
270  {
271  GetPointerS<ssa_name>(GET_NODE(use.first))->AddUseStmt(new_stmt);
272  }
273  }
274  }
275  }
276  if(schedule)
277  {
278  schedule->UpdateTime(new_stmt->index);
279  }
280 }
281 
282 const std::list<tree_nodeRef>& bloc::CGetStmtList() const
283 {
284  return list_of_stmt;
285 }
286 
287 void bloc::PushBefore(const tree_nodeRef new_stmt, const tree_nodeRef existing_stmt, const application_managerRef AppM)
288 {
289  THROW_ASSERT(number != ENTRY_BLOCK_ID, "Trying to add " + new_stmt->ToString() + " to entry");
290  THROW_ASSERT((!GET_NODE(new_stmt)) || (GET_NODE(new_stmt)->get_kind() != gimple_phi_K),
291  "Adding phi " + new_stmt->ToString() + " to statements list");
292  auto pos = list_of_stmt.begin();
293  while(pos != list_of_stmt.end())
294  {
295  if((*pos)->index == existing_stmt->index)
296  {
297  break;
298  }
299  pos++;
300  }
301  THROW_ASSERT(pos != list_of_stmt.end(), existing_stmt->ToString() + " not found in BB" + STR(number));
302  list_of_stmt.insert(pos, new_stmt);
303  update_new_stmt(AppM, new_stmt);
304 }
305 
306 void bloc::PushAfter(const tree_nodeRef new_stmt, const tree_nodeRef existing_stmt, const application_managerRef AppM)
307 {
308  THROW_ASSERT(number != ENTRY_BLOCK_ID, "Trying to add " + new_stmt->ToString() + " to entry");
309  THROW_ASSERT((!GET_NODE(new_stmt)) || (GET_NODE(new_stmt)->get_kind() != gimple_phi_K),
310  "Adding phi " + new_stmt->ToString() + " to statements list");
311  auto pos = list_of_stmt.begin();
312  while(pos != list_of_stmt.end())
313  {
314  if((*pos)->index == existing_stmt->index)
315  {
316  break;
317  }
318  pos++;
319  }
320  pos++;
321  list_of_stmt.insert(pos, new_stmt);
322  update_new_stmt(AppM, new_stmt);
323 }
324 
325 void bloc::PushFront(const tree_nodeRef statement, const application_managerRef AppM)
326 {
327  THROW_ASSERT((!GET_NODE(statement)) || (GET_NODE(statement)->get_kind() != gimple_phi_K),
328  "Adding phi " + statement->ToString() + " to statements list");
329  if(list_of_stmt.size() && GET_NODE(list_of_stmt.front())->get_kind() != gimple_label_K)
330  {
331  list_of_stmt.push_front(statement);
332  }
333  else
334  {
335  list_of_stmt.insert(std::next(list_of_stmt.begin()), statement);
336  }
337  update_new_stmt(AppM, statement);
338 }
339 
340 void bloc::PushBack(const tree_nodeRef statement, const application_managerRef AppM)
341 {
342  THROW_ASSERT(number, "Trying to add " + statement->ToString() + " to entry");
343  THROW_ASSERT((!GET_NODE(statement)) || (GET_NODE(statement)->get_kind() != gimple_phi_K),
344  "Adding phi " + statement->ToString() + " to statements list");
345  if(list_of_stmt.empty())
346  {
347  list_of_stmt.push_back(statement);
348  }
349  else
350  {
351  const auto& current_last_stmt = list_of_stmt.back();
352  if(tree_helper::LastStatement(current_last_stmt))
353  {
354  list_of_stmt.insert(std::prev(list_of_stmt.end()), statement);
355  }
356  else
357  {
358  list_of_stmt.push_back(statement);
359  }
360  }
361  update_new_stmt(AppM, statement);
362 }
363 
364 void bloc::Replace(const tree_nodeRef old_stmt, const tree_nodeRef new_stmt, const bool move_virtuals,
365  const application_managerRef AppM)
366 {
367 #if HAVE_ASSERTS
368  bool replaced = false;
369 #endif
370  for(auto temp_stmt = list_of_stmt.begin(); temp_stmt != list_of_stmt.end(); temp_stmt++)
371  {
372  if((*temp_stmt)->index == old_stmt->index)
373  {
374 #if HAVE_ASSERTS
375  replaced = true;
376 #endif
377  const auto next_stmt = std::next(temp_stmt);
378  RemoveStmt(old_stmt, AppM);
379  const auto old_ga = GetPointer<gimple_node>(GET_NODE(old_stmt));
380  const auto new_ga = GetPointer<gimple_node>(GET_NODE(new_stmt));
381  THROW_ASSERT(old_ga, "");
382  THROW_ASSERT(new_ga, "");
383  THROW_ASSERT(!old_ga->memdef || move_virtuals, STR(old_stmt) + " defines virtuals");
384  if(move_virtuals)
385  {
386  if(old_ga->memdef)
387  {
388  THROW_ASSERT(!new_ga->memdef, "");
389  new_ga->memdef = old_ga->memdef;
390  }
391  if(old_ga->memuse)
392  {
393  THROW_ASSERT(!new_ga->memuse, "");
394  new_ga->memuse = old_ga->memuse;
395  }
396  if(old_ga->vdef)
397  {
398  THROW_ASSERT(!new_ga->vdef, "");
399  new_ga->vdef = old_ga->vdef;
400  }
401  if(old_ga->vuses.size())
402  {
403  new_ga->vuses.insert(old_ga->vuses.begin(), old_ga->vuses.end());
404  }
405  if(old_ga->vovers.size())
406  {
407  new_ga->vovers.insert(old_ga->vovers.begin(), old_ga->vovers.end());
408  }
409  }
410  if(next_stmt != list_of_stmt.end())
411  {
412  PushBefore(new_stmt, *next_stmt, AppM);
413  }
414  else
415  {
416  PushBack(new_stmt, AppM);
417  }
418  break;
419  }
420  }
421  THROW_ASSERT(replaced, STR(old_stmt) + " not found");
422 }
423 
424 void bloc::RemoveStmt(const tree_nodeRef statement, const application_managerRef AppM)
425 {
426  const auto ga = GetPointer<gimple_assign>(GET_NODE(statement));
427  if((ga && (GET_NODE(ga->op1)->get_kind() == call_expr_K || GET_NODE(ga->op1)->get_kind() == aggr_init_expr_K)) ||
428  GET_NODE(statement)->get_kind() == gimple_call_K)
429  {
430  const auto cg_man = AppM->GetCallGraphManager();
431  THROW_ASSERT(cg_man, "");
432  unsigned int called_function_id;
433  if(check_function_call(statement, ga, called_function_id))
434  {
435  THROW_ASSERT(GetPointerS<const gimple_node>(GET_NODE(statement))->scpe, "statement " + statement->ToString());
436  const auto fun_id = GET_INDEX_NODE(GetPointerS<const gimple_node>(GET_NODE(statement))->scpe);
437  const auto fun_cg_vertex = cg_man->GetVertex(fun_id);
438  const auto cg = cg_man->CGetCallGraph();
440  OutEdgeIterator oei, oei_end;
441  boost::tie(oei, oei_end) = boost::out_edges(fun_cg_vertex, *cg);
442  const auto call_id = GET_INDEX_NODE(statement);
443  for(; oei != oei_end; oei++)
444  {
445  const auto& direct_calls = cg->CGetFunctionEdgeInfo(*oei)->direct_call_points;
446  auto call_it = direct_calls.find(call_id);
447  if(call_it != direct_calls.end())
448  {
449  to_remove.insert(*oei);
450  }
451  }
453  AppM->get_tree_manager(),
454  GetPointer<const function_decl>(AppM->get_tree_manager()->CGetTreeNode(
455  called_function_id))) == BUILTIN_WAIT_CALL,
456  "Call to be removed not found in call graph " + STR(call_id) + " " + STR(fun_id) + " " +
457  STR(statement) + " | " +
458  tree_helper::print_function_name(AppM->get_tree_manager(),
459  GetPointerS<function_decl>(GET_NODE(
460  GetPointerS<gimple_node>(GET_NODE(statement))->scpe))));
461  for(const auto& e : to_remove)
462  {
463  cg_man->RemoveCallPoint(e, call_id);
464  }
465  }
466  }
467 #if HAVE_ASSERTS
468  const auto original_size = list_of_stmt.size();
469 #endif
470  for(auto temp_stmt = list_of_stmt.begin(); temp_stmt != list_of_stmt.end(); temp_stmt++)
471  {
472  if((*temp_stmt)->index == statement->index)
473  {
474  list_of_stmt.erase(temp_stmt);
475  break;
476  }
477  }
478  GetPointerS<gimple_node>(GET_NODE(statement))->bb_index = 0;
479  THROW_ASSERT(original_size != list_of_stmt.size(),
480  "Statement " + statement->ToString() + " not removed from BB" + STR(number));
481  if(updated_ssa_uses)
482  {
483  const auto& uses = tree_helper::ComputeSsaUses(statement);
484  for(const auto& use : uses)
485  {
486  for(size_t counter = 0; counter < use.second; counter++)
487  {
488  GetPointerS<ssa_name>(GET_NODE(use.first))->RemoveUse(statement);
489  }
490  }
491  }
492  // TODO: fix memdef and vdef
493 }
494 
495 const std::list<tree_nodeRef>& bloc::CGetPhiList() const
496 {
497  return list_of_phi;
498 }
499 
501 {
502  list_of_phi.push_back(phi);
503  update_new_stmt(nullptr, phi);
504 }
505 
507 {
508 #if HAVE_ASSERTS
509  const auto original_size = list_of_phi.size();
510 #endif
511  for(auto temp_phi = list_of_phi.begin(); temp_phi != list_of_phi.end(); temp_phi++)
512  {
513  if((*temp_phi)->index == phi->index)
514  {
515  list_of_phi.erase(temp_phi);
516  break;
517  }
518  }
519  GetPointerS<gimple_node>(GET_NODE(phi))->bb_index = 0;
520  removed_phi++;
521  THROW_ASSERT(original_size != list_of_phi.size(), "Phi" + phi->ToString() + " not removed");
522  if(updated_ssa_uses)
523  {
524  const auto& uses = tree_helper::ComputeSsaUses(phi);
525  for(const auto& use : uses)
526  {
527  for(size_t counter = 0; counter < use.second; counter++)
528  {
529  GetPointerS<ssa_name>(GET_NODE(use.first))->RemoveUse(phi);
530  }
531  }
532  }
533  // TODO: fix memdef and vdef
534 }
535 
537 {
538  return removed_phi;
539 }
540 
542 {
543  THROW_ASSERT(not updated_ssa_uses, "SSA uses already set as updated");
544  updated_ssa_uses = true;
545 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
void PushBack(const tree_nodeRef statement, const application_managerRef AppM)
Add a statement as last non controlling statement.
virtual void visit(tree_node_visitor *const v) const
virtual function used to traverse the tree_node data structure.
boost::graph_traits< graph >::out_edge_iterator OutEdgeIterator
out_edge_iterator definition.
Definition: graph.hpp:1312
void PushBefore(const tree_nodeRef new_stmt, const tree_nodeRef existing_stmt, const application_managerRef AppM)
Add a statement before a specified one.
const unsigned int number
number is the index of the basic block.
std::string ToString() const
Print this node as string in gimple format.
tree_nodeRef op1
The second operand of the binary expression.
Definition: tree_node.hpp:3024
static bool LastStatement(const tree_nodeConstRef &statement)
Return true if statement must be the last of a basic block.
#define BB_EXIT
constant identifying the basic block node of type exit
Definition of the class representing a generic C application.
void update_new_stmt(const application_managerRef &AppM, const tree_nodeRef &new_stmt)
void Replace(const tree_nodeRef old_stmt, const tree_nodeRef new_stmt, const bool move_virtuals, const application_managerRef AppM)
Replace a statement with another one.
void PushFront(const tree_nodeRef statement, const application_managerRef AppM)
Add a statement in front of list of statements.
#define BUILTIN_WAIT_CALL
constant defining the builtin wait call intrinsic function
Definition: op_graph.hpp:358
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
bool updated_ssa_uses
consistency of ssa uses
static std::string print_function_name(const tree_managerConstRef &TM, const function_decl *fd)
Return the name of the function in a string.
const std::list< tree_nodeRef > & CGetPhiList() const
Return the list of phi.
void RemoveStmt(const tree_nodeRef statement, const application_managerRef AppM)
Remove a statement.
void manageCallGraph(const application_managerRef &AppM, const tree_nodeRef &statement)
Data structure describing a basic block at tree level.
void RemovePhi(const tree_nodeRef phi)
Remove a phi.
Abstract pure class for the tree structure.
Definition: tree_node.hpp:139
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
static void addCallPointAndExpand(CustomUnorderedSet< unsigned int > &AV, const application_managerRef AM, unsigned int caller_id, unsigned int called_id, unsigned int call_id, enum FunctionEdgeInfo::CallType call_type, int DL)
void UpdateTime(const unsigned int operation_index, bool update_cs=true)
Compute the starting and the ending time of a statement.
Definition: schedule.cpp:337
const std::list< tree_nodeRef > & CGetStmtList() const
Return the list of stmt.
This struct specifies the gimple_assign node (GCC 4.3 tree node).
Definition: tree_node.hpp:3015
Data structure used to store the schedule of the operations.
#define SEQ_VISIT_MEMBER(mask, seq, seqbasetype, method, visitor_type, visitor_obj)
macro used to traverse non empty sequences
Definition: visitor.hpp:64
void ReorderLUTs()
ReorderLUTs reorders the LUT statements to fix the def-use relations.
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
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
Classes specification of the tree_node data structures.
#define ALL_VISIT
constant used to allow member visit
Definition: visitor.hpp:71
Call graph hierarchy.
This file collects some utility functions.
void AddPhi(const tree_nodeRef phi)
Add a value to list of phi node.
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
bool check_function_call(const tree_nodeRef &statement, gimple_assign *ga, unsigned int &called_function_id)
Data structures used in operations graph.
virtual ~bloc()
Destructor.
std::list< tree_nodeRef > list_of_phi
list_of_phi is a list of eventual phi node presents in the basic block.
Wrapper to call graph.
unsigned counter[N_THREADS]
Definition: data.c:3
size_t removed_phi
Number of removed phi.
ScheduleRef schedule
The reference to the schedule.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
static void ComputeSsaUses(const tree_nodeRef &, TreeNodeMap< size_t > &uses)
recursively compute the references to the ssa_name variables used in a statement
CustomUnorderedSet< unsigned int > already_visited
Already visited tree node (used to avoid infinite recursion)
bloc(unsigned int _number)
constructor
std::list< tree_nodeRef > list_of_stmt
list_of_stmt is the list of statements stored in the basic block.
Class specification of the manager of the tree structures extracted from the raw file.
void SetSSAUsesComputed()
Set that uses of ssa have been computed.
A brief description of the C++ Header File.
size_t CGetNumberRemovedPhi() const
Return the number of removed phi.
void PushAfter(const tree_nodeRef new_stmt, const tree_nodeRef existing_stmt, const application_managerRef AppM)
Add a statement after a specified one.
#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:55 for PandA-2024.02 by doxygen 1.8.13