PandA-2024.02
c_writer.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  */
49 #include "c_writer.hpp"
50 
51 #include "config_HAVE_HOST_PROFILING_BUILT.hpp"
52 #include "config_PACKAGE_NAME.hpp"
53 #include "config_PACKAGE_VERSION.hpp"
54 #include "config_RELEASE.hpp"
55 
56 #include "Dominance.hpp"
57 #include "Parameter.hpp"
58 #include "actor_graph_backend.hpp"
59 #include "application_manager.hpp"
60 #include "basic_block.hpp"
61 #include "behavioral_helper.hpp"
62 #include "c_backend.hpp"
65 #include "call_graph_manager.hpp"
66 #include "ext_tree_node.hpp"
67 #include "function_behavior.hpp"
68 #include "hls_manager.hpp"
70 #include "instruction_writer.hpp"
71 #include "loop.hpp"
72 #include "loops.hpp"
73 #include "op_graph.hpp"
74 #include "tree_basic_block.hpp"
75 #include "tree_helper.hpp"
76 #include "tree_manager.hpp"
77 #include "tree_reindex.hpp"
78 #include "var_pp_functor.hpp"
79 
80 #if HAVE_HOST_PROFILING_BUILT
82 #endif
85 #include "hls_c_writer.hpp"
87 
88 #include <boost/range/adaptor/reversed.hpp>
89 
90 #if HAVE_UNORDERED
91 #include <boost/functional/hash/hash.hpp>
92 
94 namespace std
95 {
96  template <>
97  struct hash<std::pair<tree_nodeRef, tree_nodeRef>>
98  : public std::unary_function<std::pair<tree_nodeRef, tree_nodeRef>, std::size_t>
99  {
100  std::size_t operator()(const std::pair<tree_nodeRef, tree_nodeRef>& val) const
101  {
102  std::size_t hash_value = 0;
103  boost::hash_combine(hash_value, val.first);
104  boost::hash_combine(hash_value, val.second);
105  return hash_value;
106  }
107  };
108 } // namespace std
109 class TreeNodesPairSet : public CustomUnorderedSet<std::pair<tree_nodeRef, tree_nodeRef>>
110 {
111 };
112 #else
114  : public std::binary_function<std::pair<tree_nodeRef, tree_nodeRef>, std::pair<tree_nodeRef, tree_nodeRef>, bool>
115 {
116  public:
123  bool operator()(const std::pair<tree_nodeRef, tree_nodeRef>& x, const std::pair<tree_nodeRef, tree_nodeRef>& y) const
124  {
125  if(x.first->index == y.first->index)
126  {
127  return x.second->index < y.second->index;
128  }
129  else
130  {
131  return x.first->index < y.first->index;
132  }
133  }
134 };
135 class TreeNodesPairSet : public OrderedSetStd<std::pair<tree_nodeRef, tree_nodeRef>, TreeNodesPairSorter>
136 {
137 };
138 #endif
139 
140 CWriter::CWriter(const HLS_managerConstRef _HLSMgr, const InstructionWriterRef _instruction_writer,
141  const IndentedOutputStreamRef _indented_output_stream, const ParameterConstRef _Param, bool _verbose)
142  : HLSMgr(_HLSMgr),
143  TM(_HLSMgr->get_tree_manager()),
144  indented_output_stream(_indented_output_stream),
145  instrWriter(_instruction_writer),
146  bb_label_counter(0),
147  verbose(_verbose),
148  Param(_Param),
149  debug_level(_Param->get_class_debug_level("CWriter")),
150  output_level(_Param->getOption<int>(OPT_output_level)),
151  fake_max_tree_node_id(0),
152  dominators(nullptr),
153  post_dominators(nullptr)
154 {
155 }
156 
157 CWriter::~CWriter() = default;
158 
161  const ParameterConstRef parameters, const bool verbose)
162 {
163  const auto app_man = RefcountCast<const application_manager>(hls_man);
164  switch(c_backend_info->type)
165  {
166 #if HAVE_HOST_PROFILING_BUILT
167  case(CBackendInformation::CB_BBP):
168  {
169  const auto instruction_writer = InstructionWriter::CreateInstructionWriter(
170  ActorGraphBackend_Type::BA_NONE, app_man, indented_output_stream, parameters);
171  return CWriterRef(
172  new BasicBlocksProfilingCWriter(hls_man, instruction_writer, indented_output_stream, parameters, verbose));
173  }
174 #endif
175 #if HAVE_HLS_BUILT
176  case(CBackendInformation::CB_DISCREPANCY_ANALYSIS):
177  {
178  const InstructionWriterRef instruction_writer(
179  new discrepancy_instruction_writer(app_man, indented_output_stream, parameters));
180 
181  return CWriterRef(new DiscrepancyAnalysisCWriter(c_backend_info, hls_man, instruction_writer,
182  indented_output_stream, parameters, verbose));
183  }
184 #endif
185  case(CBackendInformation::CB_HLS):
186  {
187  const InstructionWriterRef instruction_writer(
188  new HLSInstructionWriter(app_man, indented_output_stream, parameters));
189  return CWriterRef(
190  new HLSCWriter(c_backend_info, hls_man, instruction_writer, indented_output_stream, parameters, verbose));
191  }
192  case(CBackendInformation::CB_SEQUENTIAL):
193  {
194  const auto instruction_writer = InstructionWriter::CreateInstructionWriter(
195  ActorGraphBackend_Type::BA_NONE, app_man, indented_output_stream, parameters);
196  return CWriterRef(new CWriter(hls_man, instruction_writer, indented_output_stream, parameters, verbose));
197  }
198  default:
199  {
200  THROW_UNREACHABLE("");
201  }
202  }
203  return CWriterRef();
204 }
205 
206 void CWriter::declare_cast_types(unsigned int funId, CustomSet<std::string>& locally_declared_types)
207 {
208  const auto function_behavior = HLSMgr->CGetFunctionBehavior(funId);
209  const auto BH = function_behavior->CGetBehavioralHelper();
210  const auto inGraph = function_behavior->CGetOpGraph(FunctionBehavior::DFG);
211  // I simply have to go over all the vertices and look for types used for type casting;
212  VertexIterator v, vEnd;
213  for(boost::tie(v, vEnd) = boost::vertices(*inGraph); v != vEnd; v++)
214  {
215  const auto& node = inGraph->CGetOpNodeInfo(*v)->node;
216  if(node)
217  {
218  TreeNodeConstSet types;
219  BH->GetTypecast(node, types);
220  for(const auto& t : types)
221  {
222  DeclareType(t, BH, locally_declared_types);
223  }
224  }
225  }
226 }
227 
229 {
231  instrWriter->Initialize();
232  globally_declared_types.clear();
233  globallyDeclVars.clear();
234  additionalIncludes.clear();
235  writtenIncludes.clear();
236 }
237 
238 void CWriter::WriteBodyLoop(const unsigned int function_index, const unsigned int, vertex current_vertex, bool bracket)
239 {
240  writeRoutineInstructions_rec(current_vertex, bracket, function_index);
241 }
242 
243 void CWriter::WriteFunctionBody(unsigned int function_id)
244 {
245  const FunctionBehaviorConstRef function_behavior = HLSMgr->CGetFunctionBehavior(function_id);
246  const OpGraphConstRef op_graph = function_behavior->CGetOpGraph(FunctionBehavior::CFG);
247  const BehavioralHelperConstRef BH = function_behavior->CGetBehavioralHelper();
248  var_pp_functorRef variableFunctor(new std_var_pp_functor(BH));
249  OpVertexSet vertices(op_graph);
250  VertexIterator statement, statement_end;
251  boost::tie(statement, statement_end);
252  boost::tie(statement, statement_end) = boost::vertices(*op_graph);
253  vertices.insert(statement, statement_end);
254  THROW_ASSERT(vertices.size() > 0, "Graph for function " + BH->get_function_name() + " is empty");
255  writeRoutineInstructions(function_id, vertices, variableFunctor);
256 }
257 
258 void CWriter::WriteFunctionImplementation(unsigned int function_id)
259 {
260  StartFunctionBody(function_id);
261  WriteFunctionBody(function_id);
262  EndFunctionBody(function_id);
263 }
264 
266 {
268 #ifdef __cplusplus
269 typedef bool _Bool;
270 #endif
271 
272 #include <sys/types.h>
273 )");
274 
275  bool is_readc_needed = false;
276  bool is_builtin_cond_expr32 = false;
277  for(auto extfun : HLSMgr->get_functions_without_body())
278  {
279  const BehavioralHelperConstRef BH = HLSMgr->CGetFunctionBehavior(extfun)->CGetBehavioralHelper();
280  if(BH->get_function_name() == "__bambu_readc" || BH->get_function_name() == "__bambu_read4c")
281  {
282  is_readc_needed = true;
283  }
284  if(BH->get_function_name() == "__builtin_cond_expr32")
285  {
286  is_builtin_cond_expr32 = true;
287  }
288  }
289  if(is_readc_needed)
290  {
291  indented_output_stream->Append("#include <unistd.h>\n");
293  "short int __bambu_readc(int fd){char buf[1];int res = read(fd,buf,1);return res > 0 ? buf[0] : -1;}\n");
295  "long long int __bambu_read4c(int fd){long long int buf;int res = read(fd,&buf,4);return res == 4 ? buf : "
296  "(res==3 ? (buf|(1ULL<<35)) : (res==2 ? (buf|(1ULL<<35)|(1ULL<<34)) : (res == 1 ? "
297  "(buf|(1ULL<<35)|(1ULL<<34)|(1ULL<<33)) : "
298  "(buf|(1ULL<<35)|(1ULL<<34)|(1ULL<<33)|(1ULL<<32))) ));}\n");
299  }
300  if(is_builtin_cond_expr32)
301  {
302  indented_output_stream->Append("#define __builtin_cond_expr32(cond, value1, value2) cond ? value1 : value2\n\n");
303  }
304  // TODO: add bambu param manager implementation
305 }
306 
308 {
310  instrWriter->write_declarations();
311 
313  CustomOrderedSet<unsigned int> functions = HLSMgr->get_functions_with_body();
314  THROW_ASSERT(functions.size() > 0, "at least one function is expected");
315  unsigned int first_fun = *functions.begin();
316  const auto BH = HLSMgr->CGetFunctionBehavior(first_fun)->CGetBehavioralHelper();
317 
318  const auto& gblVariables = HLSMgr->GetGlobalVariables();
319  // Write the declarations for the global variables
320  var_pp_functorRef variableFunctor(new std_var_pp_functor(BH));
321  for(const auto& glbVar : gblVariables)
322  {
323  DeclareVariable(glbVar, globallyDeclVars, globally_declared_types, BH, variableFunctor);
324  }
326  if(HLSMgr->CGetCallGraphManager()->ExistsAddressedFunction())
327  {
328  indented_output_stream->Append("#include <stdarg.h>\n\n");
329  indented_output_stream->Append("void " + STR(BUILTIN_WAIT_CALL) + "(void * ptr, ...);\n");
330  }
331 }
332 
334 {
335  const auto FB = HLSMgr->CGetFunctionBehavior(tn->index);
336  const auto BH = FB->CGetBehavioralHelper();
337  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Declaring function types for " + BH->get_function_name());
338 
339  // In case the function parameters are of a non built_in type I have
340  // to declare their type
341 
342  for(const auto& parameter_type : BH->GetParameterTypes())
343  {
344  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Parameter type " + STR(parameter_type));
345  DeclareType(parameter_type, BH, globally_declared_types);
346  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Parameter type " + STR(parameter_type));
347  }
348  const auto return_type = tree_helper::GetFunctionReturnType(tn);
349  if(return_type)
350  {
351  DeclareType(return_type, BH, globally_declared_types);
352  }
353  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Declared function types for " + BH->get_function_name());
354 }
355 
356 const CustomSet<unsigned int> CWriter::GetLocalVariables(const unsigned int function_id) const
357 {
358  const auto inGraph = HLSMgr->CGetFunctionBehavior(function_id)->CGetOpGraph(FunctionBehavior::DFG);
360  // I simply have to go over all the vertices and get the used variables;
361  // the variables which have to be declared are all those variables but
362  // the globals ones
363  VertexIterator v, vEnd;
364  for(boost::tie(v, vEnd) = boost::vertices(*inGraph); v != vEnd; v++)
365  {
366  const auto& vars_temp = inGraph->CGetOpNodeInfo(*v)->cited_variables;
367  vars.insert(vars_temp.begin(), vars_temp.end());
368  }
369  return vars;
370 }
371 
372 void CWriter::WriteFunctionDeclaration(const unsigned int funId)
373 {
374  const auto FB = HLSMgr->CGetFunctionBehavior(funId);
375  const auto BH = FB->CGetBehavioralHelper();
376  const auto funName = BH->get_function_name();
377  if(funName != "main")
378  {
379  instrWriter->declareFunction(funId);
380  indented_output_stream->Append(";\n\n");
381  }
382 }
383 
384 void CWriter::StartFunctionBody(const unsigned int function_id)
385 {
386  instrWriter->declareFunction(function_id);
387  indented_output_stream->Append("\n{\n");
388 
389  const auto BH = HLSMgr->CGetFunctionBehavior(function_id)->CGetBehavioralHelper();
390  auto vars = GetLocalVariables(function_id);
391 
392  for(const auto& funParam : BH->GetParameters())
393  {
394  vars.erase(funParam->index);
395  }
396 
397  for(const auto& gblVariable : HLSMgr->GetGlobalVariables())
398  {
399  vars.erase(gblVariable->index);
400  }
401 
402  var_pp_functorRef variableFunctor(new std_var_pp_functor(BH));
403  CustomSet<unsigned int> already_declared_variables;
404  CustomSet<std::string> locally_declared_types;
405  declare_cast_types(function_id, locally_declared_types);
406  DeclareLocalVariables(vars, already_declared_variables, locally_declared_types, BH, variableFunctor);
407 }
408 
409 void CWriter::EndFunctionBody(unsigned int funId)
410 {
412  if(verbose)
413  {
414  indented_output_stream->Append("//end of function; id: " + STR(funId) + "\n");
415  }
417  basic_block_prefix.clear();
418  basic_block_tail.clear();
419  renaming_table.clear();
420 }
421 
423 {
424 }
425 
427 {
428 }
429 
430 void CWriter::writeRoutineInstructions_rec(vertex current_vertex, bool bracket, const unsigned int function_index)
431 {
433  const BBNodeInfoConstRef& bb_node_info = local_rec_bb_fcfgGraph->CGetBBNodeInfo(current_vertex);
434  const unsigned int bb_number = bb_node_info->block->number;
435 
436  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Starting writing BB" + STR(bb_number));
438  THROW_ASSERT(bb_frontier.find(current_vertex) == bb_frontier.end(),
439  "current_vertex cannot be part of the basic block frontier");
440  // if this basic block has already been analyzed do nothing
441  if(bb_analyzed.find(current_vertex) != bb_analyzed.end())
442  {
444  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--BB" + STR(bb_number) + " already written");
445  return;
446  }
447  // mark this basic block as analyzed
448  bb_analyzed.insert(current_vertex);
449  // print a comment with info on the basicblock
450  if(verbose)
451  {
452  indented_output_stream->Append("//Basic block " + STR(bb_number) + " - loop " + STR(bb_node_info->loop_id) +
453  "\n");
454  }
455  // check if some extra strings must be printed before or after the basic
456  // block. this is used for splitting the phi nodes
457  bool add_phi_nodes_assignment_prefix = basic_block_prefix.count(bb_number);
458  bool add_phi_nodes_assignment = basic_block_tail.count(bb_number);
459  // get immediate post-dominator and check if it has to be examined
460  vertex bb_PD = post_dominators->get_immediate_dominator(current_vertex);
461 #ifndef NDEBUG
462  {
463  const auto bb_node_info_pd = local_rec_bb_fcfgGraph->CGetBBNodeInfo(bb_PD);
464  const auto& bb_number_PD = bb_node_info_pd->block->number;
465 
466  std::string frontier_string;
467  for(const auto bb : bb_frontier)
468  {
469  frontier_string += "BB" + STR(local_rec_bb_fcfgGraph->CGetBBNodeInfo(bb)->block->number) + " ";
470  }
471  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Frontier at the moment is: " + frontier_string);
472  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Its post-dominator is BB" + STR(bb_number_PD));
473  }
474 #endif
475  bool analyze_bb_PD = !bb_frontier.count(bb_PD) && !bb_analyzed.count(bb_PD);
476  if(analyze_bb_PD)
477  {
478  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Post dominator will be examinated");
479  bb_frontier.insert(bb_PD);
480  }
482  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Looking for last statement");
484  vertex last_stmt = NULL_VERTEX;
485  bool is_there = false;
486  const auto& stmts_list = bb_node_info->statements_list;
487  for(const auto st : boost::adaptors::reverse(stmts_list))
488  {
489  if(!local_rec_instructions.count(st))
490  {
491  continue;
492  }
494  {
495  continue;
496  }
497  if((GET_TYPE(local_rec_cfgGraph, st) & TYPE_INIT) != 0)
498  {
499  continue;
500  }
502  "Considering operation " + GET_NAME(local_rec_cfgGraph, st));
504  "This is basic block is not empty in this task. Last operation to be printed id " +
506  last_stmt = st;
507  is_there = true;
508  break;
509  }
512  bool last_statement_is_a_cond_or_goto =
513  is_there and local_rec_behavioral_helper->end_with_a_cond_or_goto(bb_node_info->block) != 0 &&
514  last_stmt == stmts_list.back();
515 
516  THROW_ASSERT(!last_statement_is_a_cond_or_goto || !is_there ||
517  (last_statement_is_a_cond_or_goto && last_stmt == stmts_list.back()),
518  "inconsistent recursion");
519  // check if the basic block starts with a label
520  bool start_with_a_label = local_rec_behavioral_helper->start_with_a_label(bb_node_info->block);
521  if(start_with_a_label)
522  {
523  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Basic block starts with a label");
524  }
525  // check if the label is already in the goto list
526  bool add_bb_label = goto_list.find(current_vertex) != goto_list.end();
527  if(add_bb_label)
528  {
529  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Basic block should start with a label");
530  }
531 
532  if(!add_bb_label && !start_with_a_label && boost::in_degree(current_vertex, *local_rec_bb_fcfgGraph) > 1)
533  {
535  "Basic block has an indegree > 1 and not associated label");
536  InEdgeIterator inE, inEEnd;
537  for(boost::tie(inE, inEEnd) = boost::in_edges(current_vertex, *local_rec_bb_fcfgGraph); inE != inEEnd; inE++)
538  {
539  vertex source = boost::source(*inE, *local_rec_bb_fcfgGraph);
540  const auto pred_bb_node_info = local_rec_bb_fcfgGraph->CGetBBNodeInfo(source);
541  // This condition match first basic block of case preceded by a case without break
542  if(pred_bb_node_info->statements_list.size() &&
543  (GET_TYPE(local_rec_cfgGraph, *(pred_bb_node_info->statements_list.rbegin())) & TYPE_SWITCH) &&
544  post_dominators->get_immediate_dominator(source) != current_vertex)
545  {
547  "Basic block is the first case of a case preceded by a case without break");
548  add_bb_label = true;
549  break;
550  }
551  // Basic block start the body of a short circuit
552  else if(!bb_analyzed.count(source) && !((FB_CFG_SELECTOR & local_rec_bb_fcfgGraph->GetSelector(*inE))))
553  {
555  "Basic block should start with a label since is the body of a short-circuit");
556  add_bb_label = true;
557  break;
558  }
559  // Basic block is a header loop, but it does not end with while or for
560  else if((!bb_analyzed.count(source) || current_vertex == source) &&
561  (stmts_list.empty() ||
562  ((GET_TYPE(local_rec_cfgGraph, *(stmts_list.rbegin())) & (TYPE_WHILE | TYPE_FOR)) == 0)))
563  {
565  "Basic block is the header of a loop and it does not end with while or for");
566  add_bb_label = true;
567  break;
568  }
569  }
570  }
571  add_bb_label = add_bb_label && !start_with_a_label;
572  bool add_semicolon = false;
574  if(bracket)
575  {
576  if(analyze_bb_PD || is_there || add_bb_label || add_phi_nodes_assignment || add_phi_nodes_assignment_prefix)
577  {
579  }
580  else
581  {
582  add_semicolon = true;
583  }
584  }
585  if(add_bb_label)
586  {
587  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "A label should be added at the beginning");
588  THROW_ASSERT(basic_blocks_labels.count(bb_number), "I do not know the destination: " + STR(bb_number));
589  indented_output_stream->Append(basic_blocks_labels.at(bb_number) + ":;\n");
590  add_semicolon = true;
591  }
592  else if(start_with_a_label)
593  {
594  add_semicolon = true;
595  }
596  WriteBBHeader(bb_number, function_index);
597 
598  std::list<vertex>::const_iterator vIter, vIterBegin;
599  vIter = stmts_list.begin();
600  vIterBegin = vIter;
601  if(is_there)
602  {
604  "There are instructions to be printed for this pair task - basic block");
605 
606  // fill the renaming table in case it is needed
607  if(renaming_table.find(current_vertex) != renaming_table.end())
608  {
609  for(const auto& rvt : renaming_table.find(current_vertex)->second)
610  {
611  BehavioralHelper::rename_a_variable(rvt.first, rvt.second);
612  }
613  }
614  bool label_has_to_be_printed = start_with_a_label;
615  bool prefix_has_to_be_printed = basic_block_prefix.find(bb_number) != basic_block_prefix.end();
616  do
617  {
618  // We can print results of split of phi nodes if they have not yet been printed and if label has already been
619  // printed (or there was not any label to be printed)
620  if(prefix_has_to_be_printed and not label_has_to_be_printed)
621  {
622  prefix_has_to_be_printed = false;
623  indented_output_stream->Append(basic_block_prefix.find(bb_number)->second);
624  }
625  if(local_rec_instructions.find(*vIter) == local_rec_instructions.end())
626  {
627  continue;
628  }
629  // If there is not any label to be printed, label_has_to_be_printed is already false, otherwise the label will
630  // be printed during this loop iteration
631  label_has_to_be_printed = false;
633  "Preparing printing of operation " + GET_NAME(local_rec_cfgGraph, *vIter));
634  // Write in the C file extra information before the instruction itself
635  if(verbose)
636  {
637  indented_output_stream->Append("//Instruction: " + GET_NAME(local_rec_cfgGraph, *vIter) + "\n");
638  }
640  // Now I print the instruction
641  if(start_with_a_label && vIter == vIterBegin)
642  {
643  InEdgeIterator inE, inEEnd;
644  for(boost::tie(inE, inEEnd) = boost::in_edges(current_vertex, *local_rec_bb_fcfgGraph); inE != inEEnd;
645  inE++)
646  {
648  {
649  indented_output_stream->Append("//start of a loop\n");
650  }
651  }
652  }
653  bool isLastIntruction = last_stmt == *vIter;
655  bool print_phi_now = ((GET_TYPE(local_rec_cfgGraph, *vIter) &
658  if(add_phi_nodes_assignment && isLastIntruction && print_phi_now)
659  {
660  indented_output_stream->Append(basic_block_tail.find(bb_number)->second);
661  }
662  if((GET_TYPE(local_rec_cfgGraph, *vIter) & (TYPE_VPHI)) == 0)
663  {
664  if(GET_TYPE(local_rec_cfgGraph, *vIter) & (TYPE_WHILE | TYPE_FOR) and verbose and
665  local_rec_function_behavior->CGetLoops()->CGetLoop(bb_node_info->loop_id)->loop_type & DOALL_LOOP)
666  {
667  indented_output_stream->Append("//#pragma omp parallel for\n");
668  }
670  if((GET_TYPE(local_rec_cfgGraph, *vIter) & TYPE_LABEL) == 0)
671  {
672  add_semicolon = false;
673  }
674  }
675  else if(verbose)
676  {
677  indented_output_stream->Append("//(removed virtual phi instruction)\n");
678  }
679  // Write in the C file extra information after the instruction statement
681  if(!isLastIntruction)
682  {
683  continue;
684  }
686  if(add_phi_nodes_assignment && !print_phi_now)
687  {
688  indented_output_stream->Append(basic_block_tail.find(bb_number)->second);
689  }
690  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---This is not the last statement");
691  // Now I check if this is a control statement and I consequently print
692  // the instructions contained in its branches
693  if(GET_TYPE(local_rec_cfgGraph, *vIter) & TYPE_IF)
694  {
695  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Operation is an if");
696  const unsigned int& bb_true_number = bb_node_info->block->true_edge;
697  THROW_ASSERT(bb_graph_info->bb_index_map.find(bb_true_number) != bb_graph_info->bb_index_map.end(),
698  "BB" + STR(bb_true_number) + " does not exist");
699  const vertex true_vertex = bb_graph_info->bb_index_map.find(bb_true_number)->second;
700  THROW_ASSERT(bb_graph_info->bb_index_map.find(bb_node_info->block->false_edge) !=
701  bb_graph_info->bb_index_map.end(),
702  "BB" + STR(bb_node_info->block->false_edge) + " does not exist");
703  vertex false_vertex = bb_graph_info->bb_index_map.find(bb_node_info->block->false_edge)->second;
704  bool add_false_to_goto = false;
705  if(bb_frontier.find(true_vertex) == bb_frontier.end())
706  {
707  if(bb_frontier.find(false_vertex) == bb_frontier.end() &&
708  goto_list.find(false_vertex) == goto_list.end())
709  {
710  goto_list.insert(false_vertex);
711  add_false_to_goto = true;
712  }
713  if(bb_analyzed.find(true_vertex) == bb_analyzed.end())
714  {
715  writeRoutineInstructions_rec(true_vertex, true, function_index);
716  }
717  else
718  {
719  THROW_ASSERT(basic_blocks_labels.find(bb_true_number) != basic_blocks_labels.end(),
720  "I do not know the destination");
721  indented_output_stream->Append(" goto " + basic_blocks_labels.find(bb_true_number)->second + ";\n");
722  goto_list.insert(true_vertex);
723  }
724  }
725  else
726  {
728  }
729  if(add_false_to_goto)
730  {
731  goto_list.erase(false_vertex);
732  }
734  if(bb_frontier.find(false_vertex) == bb_frontier.end())
735  {
736  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "False BB is not on the frontier");
737  false_vertex = bb_graph_info->bb_index_map.find(bb_node_info->block->false_edge)->second;
739  boost::edge(current_vertex, false_vertex, *local_rec_bb_fcfgGraph).first)))
740  {
741  indented_output_stream->Append("else\n");
742  if(bb_analyzed.find(false_vertex) == bb_analyzed.end())
743  {
744  writeRoutineInstructions_rec(false_vertex, true, function_index);
745  }
746  else
747  {
748  THROW_ASSERT(basic_blocks_labels.find(bb_node_info->block->false_edge) !=
749  basic_blocks_labels.end(),
750  "I do not know the destination");
752  " goto " + basic_blocks_labels.find(bb_node_info->block->false_edge)->second + ";\n");
753  }
754  }
756  else
757  {
758  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Target is a header");
759  const vertex target =
760  boost::target(boost::edge(current_vertex, false_vertex, *local_rec_bb_fcfgGraph).first,
762  const BBNodeInfoConstRef target_bb_node_info = local_rec_bb_fcfgGraph->CGetBBNodeInfo(target);
764  if(target_bb_node_info->statements_list.empty() or
765  ((GET_TYPE(local_rec_cfgGraph, *(target_bb_node_info->statements_list.rbegin())) &
766  (TYPE_WHILE | TYPE_FOR)) == 0))
767  {
768  indented_output_stream->Append("else\n");
769  THROW_ASSERT(basic_blocks_labels.find(bb_node_info->block->false_edge) !=
770  basic_blocks_labels.end(),
771  "I do not know the destination");
773  " goto " + basic_blocks_labels.find(bb_node_info->block->false_edge)->second + ";\n");
774  }
775  }
776  }
777  }
778  else if(GET_TYPE(local_rec_cfgGraph, *vIter) & (TYPE_WHILE | TYPE_FOR))
779  {
780  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Operation is a while or a for");
781  const unsigned int& bb_true_number = bb_node_info->block->true_edge;
782  const vertex true_vertex = bb_graph_info->bb_index_map.find(bb_true_number)->second;
783  if(bb_frontier.find(true_vertex) == bb_frontier.end())
784  {
785  if(bb_analyzed.find(true_vertex) == bb_analyzed.end())
786  {
788  bb_node_info->block->number, true_vertex, true);
789  }
790  else
791  {
792  THROW_ERROR("Body of a loop has yet been printed before the while statement");
793  }
794  }
795  else
796  {
797  return;
798  }
799 
800  const unsigned int bb_false_number = bb_node_info->block->false_edge;
801  const vertex false_vertex = bb_graph_info->bb_index_map.find(bb_false_number)->second;
802  if(bb_frontier.find(false_vertex) == bb_frontier.end())
803  {
804  if(bb_analyzed.find(false_vertex) == bb_analyzed.end())
805  {
806  writeRoutineInstructions_rec(false_vertex, false, function_index);
807  }
808  else
809  {
810  indented_output_stream->Append("goto " + basic_blocks_labels.find(bb_false_number)->second + ";\n");
811  goto_list.insert(false_vertex);
812  }
813  }
814  }
815  else if(GET_TYPE(local_rec_cfgGraph, *vIter) & TYPE_MULTIIF)
816  {
817  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Operation is a multiif");
818  unsigned int node_id = local_rec_cfgGraph->CGetOpNodeInfo(last_stmt)->GetNodeId();
819  const tree_nodeRef node = TM->get_tree_node_const(node_id);
820  THROW_ASSERT(node->get_kind() == gimple_multi_way_if_K, "unexpected node");
821  auto* gmwi = GetPointer<gimple_multi_way_if>(node);
822  std::map<unsigned int, bool> add_elseif_to_goto;
823  for(const auto& cond : gmwi->list_of_cond)
824  {
825  unsigned int bb_index_num = cond.second;
826  const vertex bb_vertex = bb_graph_info->bb_index_map.find(bb_index_num)->second;
827  if(cond != gmwi->list_of_cond.front())
828  {
829  bool to_be_added =
830  bb_frontier.find(bb_vertex) == bb_frontier.end() && goto_list.find(bb_vertex) == goto_list.end();
831  add_elseif_to_goto[bb_index_num] = to_be_added;
832  if(to_be_added)
833  {
834  goto_list.insert(bb_vertex);
835  }
836  }
837  else
838  {
839  add_elseif_to_goto[bb_index_num] = false;
840  }
841  }
842  for(const auto& cond : gmwi->list_of_cond)
843  {
844  unsigned int bb_index_num = cond.second;
845  const vertex bb_vertex = bb_graph_info->bb_index_map.find(bb_index_num)->second;
846  if(cond != gmwi->list_of_cond.front())
847  {
848  if(cond.first)
849  {
850  indented_output_stream->Append("else if(");
854  }
855  else
856  {
857  indented_output_stream->Append("else\n");
858  }
859  }
860  if(add_elseif_to_goto.find(bb_index_num) != add_elseif_to_goto.end() &&
861  add_elseif_to_goto.find(bb_index_num)->second)
862  {
863  goto_list.erase(bb_vertex);
864  }
865  if(bb_frontier.find(bb_vertex) == bb_frontier.end())
866  {
867  if(bb_analyzed.find(bb_vertex) == bb_analyzed.end())
868  {
869  writeRoutineInstructions_rec(bb_vertex, true, function_index);
870  }
871  else
872  {
873  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Successor has already been examined");
874 
875  THROW_ASSERT(basic_blocks_labels.find(bb_index_num) != basic_blocks_labels.end(),
876  "I do not know the destination " + STR(bb_index_num));
877  indented_output_stream->Append(" goto " + basic_blocks_labels.find(bb_index_num)->second +
878  ";\n");
879  goto_list.insert(bb_vertex);
880  }
881  }
882  else
883  {
885  }
886  }
887  }
888  else if(GET_TYPE(local_rec_cfgGraph, *vIter) & TYPE_SWITCH)
889  {
890  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Operation is a switch");
893  OutEdgeIterator oE, oEEnd;
894  for(boost::tie(oE, oEEnd) = boost::out_edges(current_vertex, *local_rec_bb_fcfgGraph); oE != oEEnd; oE++)
895  {
896  bool empty_block = false;
898  const BBNodeInfoConstRef next_bb_node_info = local_rec_bb_fcfgGraph->CGetBBNodeInfo(next_bb);
899 #ifndef NDEBUG
900  const unsigned int bb_number_next_bb = next_bb_node_info->block->number;
901 #endif
902  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Examining successor " + STR(bb_number_next_bb));
906  for(eIdBeg = Set.begin(), eIdEnd = Set.end(); eIdBeg != eIdEnd; ++eIdBeg)
907  {
908  if(*eIdBeg == default_COND)
909  {
910  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Successor is default case");
911  if(next_bb == post_dominators->get_immediate_dominator(current_vertex))
912  {
914  empty_block = true;
915  indented_output_stream->Append("default:\n");
916  if(current_vertex == dominators->get_immediate_dominator(next_bb))
917  {
918  analyze_bb_PD = true;
919  }
920  break;
921  }
922  indented_output_stream->Append("default");
923  }
924  else
925  {
926  if(next_bb == bb_PD)
927  {
928  empty_block = true;
929  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Removed current basic block");
930  }
931 
934  }
936  }
937  if(empty_block)
938  {
939  indented_output_stream->Append("break;\n");
940  continue;
941  }
942  if(bb_analyzed.find(next_bb) == bb_analyzed.end())
943  {
944  writeRoutineInstructions_rec(next_bb, true, function_index);
945  indented_output_stream->Append("break;\n");
946  }
947  else
948  {
949  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Successor has already been examined");
950  const unsigned int next_bb_number = next_bb_node_info->block->number;
951 
952  THROW_ASSERT(basic_blocks_labels.find(next_bb_number) != basic_blocks_labels.end(),
953  "I do not know the destination " + STR(next_bb_number));
954  indented_output_stream->Append(" goto " + basic_blocks_labels.find(next_bb_number)->second + ";\n");
955  }
956  }
958  }
959  else if(local_rec_behavioral_helper->end_with_a_cond_or_goto(bb_node_info->block))
960  {
961  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Basic block ends with a cond or a goto");
962  if(last_statement_is_a_cond_or_goto)
963  {
965  OutEdgeIterator oE, oEEnd;
966  for(boost::tie(oE, oEEnd) = boost::out_edges(current_vertex, *local_rec_bb_fcfgGraph); oE != oEEnd; oE++)
967  {
969  if(bb_frontier.find(next_bb) != bb_frontier.end())
970  {
971  continue;
972  }
973  goto_list.insert(next_bb);
974  }
975  }
976  }
977  else
978  {
979  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---It is not a special operation");
980  const vertex bbentry = local_rec_bb_fcfgGraph->CGetBBGraphInfo()->entry_vertex;
981  if(current_vertex == bbentry)
982  {
984  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Ended writing basic block " + STR(bb_number));
985  return;
986  }
987  THROW_ASSERT(boost::out_degree(current_vertex, *local_rec_bb_fcfgGraph) <= 1, "only one edge expected");
988  OutEdgeIterator oE, oEEnd;
989  for(boost::tie(oE, oEEnd) = boost::out_edges(current_vertex, *local_rec_bb_fcfgGraph); oE != oEEnd; oE++)
990  {
992  if(bb_frontier.find(next_bb) != bb_frontier.end())
993  {
995  "Not adding goto since target is in the frontier");
996  continue;
997  }
999  {
1001  const BBNodeInfoConstRef target_bb_node_info = local_rec_bb_fcfgGraph->CGetBBNodeInfo(target);
1002  if(target_bb_node_info->statements_list.size() and
1003  (GET_TYPE(local_rec_cfgGraph, *(target_bb_node_info->statements_list.rbegin())) &
1004  (TYPE_WHILE | TYPE_FOR)))
1005  {
1007  "Not adding a goto since target is a while/for");
1008  continue;
1009  }
1010  }
1011  if(boost::in_degree(next_bb, *local_rec_bb_fcfgGraph) == 1)
1012  {
1013  writeRoutineInstructions_rec(next_bb, false, function_index);
1014  }
1015  else
1016  {
1017  const BBNodeInfoConstRef next_bb_node_info = local_rec_bb_fcfgGraph->CGetBBNodeInfo(next_bb);
1018  const unsigned int next_bb_number = next_bb_node_info->block->number;
1019  THROW_ASSERT(basic_blocks_labels.find(next_bb_number) != basic_blocks_labels.end(),
1020  "I do not know the destination");
1021  indented_output_stream->Append(" goto " + basic_blocks_labels.find(next_bb_number)->second + ";\n");
1022  goto_list.insert(next_bb);
1023  }
1024  }
1025  }
1026  } while(*vIter++ != last_stmt);
1027  }
1028  else
1029  {
1030  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "is_there is false");
1032  if(add_phi_nodes_assignment)
1033  {
1034  indented_output_stream->Append(basic_block_tail.find(bb_number)->second);
1035  add_semicolon = false;
1036  }
1037  if(!local_rec_behavioral_helper->end_with_a_cond_or_goto(bb_node_info->block) &&
1038  ((stmts_list.empty()) ||
1039  ((GET_TYPE(local_rec_cfgGraph, *stmts_list.rbegin()) & (TYPE_SWITCH | TYPE_WHILE | TYPE_FOR)) == 0)))
1040  {
1041  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Not end with a cond or goto nor switch");
1042  const vertex bbentry = local_rec_bb_fcfgGraph->CGetBBGraphInfo()->entry_vertex;
1043  if(current_vertex == bbentry)
1044  {
1046  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Ended writing basic block " + STR(bb_number));
1047  return;
1048  }
1049  THROW_ASSERT(boost::out_degree(current_vertex, *local_rec_bb_fcfgGraph) <= 1,
1050  "only one edge expected BB(" + STR(bb_number) + ") Fun(" +
1052  OutEdgeIterator oE, oEEnd;
1053  for(boost::tie(oE, oEEnd) = boost::out_edges(current_vertex, *local_rec_bb_fcfgGraph); oE != oEEnd; oE++)
1054  {
1055  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Examining the only? successor");
1056  vertex next_bb = boost::target(*oE, *local_rec_bb_fcfgGraph);
1057  if(bb_frontier.find(next_bb) != bb_frontier.end() or
1058  boost::in_degree(next_bb, *local_rec_bb_fcfgGraph) == 1)
1059  {
1060  continue;
1061  }
1064  {
1066  const BBNodeInfoConstRef target_bb_node_info = local_rec_bb_fcfgGraph->CGetBBNodeInfo(target);
1067  if(target_bb_node_info->statements_list.size() and
1068  (GET_TYPE(local_rec_cfgGraph, *(target_bb_node_info->statements_list.rbegin())) &
1069  (TYPE_WHILE | TYPE_FOR)))
1070  {
1071  continue;
1072  }
1073  }
1074 
1075  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Successor does not belong to frontier");
1076  const BBNodeInfoConstRef next_bb_node_info = local_rec_bb_fcfgGraph->CGetBBNodeInfo(next_bb);
1077  const unsigned int next_bb_number = next_bb_node_info->block->number;
1078  THROW_ASSERT(basic_blocks_labels.find(next_bb_number) != basic_blocks_labels.end(),
1079  "I do not know the destination");
1080  indented_output_stream->Append(" goto " + basic_blocks_labels.find(next_bb_number)->second + ";\n");
1081  goto_list.insert(next_bb);
1082  add_semicolon = false;
1083  }
1084  }
1085  }
1086  if(add_semicolon)
1087  {
1088  indented_output_stream->Append(";\n");
1089  }
1090 
1091  if(analyze_bb_PD)
1092  {
1093  // recurse on the post dominator
1094  bb_frontier.erase(bb_PD);
1095  THROW_ASSERT(bb_analyzed.find(bb_PD) == bb_analyzed.end(),
1096  "something wrong happened " + STR(local_rec_bb_fcfgGraph->CGetBBNodeInfo(bb_PD)->block->number) +
1097  " Fun(" + STR(local_rec_behavioral_helper->get_function_index()) + ")");
1098  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Printing the post dominator");
1099  writeRoutineInstructions_rec(bb_PD, false, function_index);
1100  }
1101  if((analyze_bb_PD || is_there || add_bb_label || add_phi_nodes_assignment || add_phi_nodes_assignment_prefix) &&
1102  bracket)
1103  {
1105  }
1107  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Ended writing basic block " + STR(bb_number));
1108 }
1109 
1110 void CWriter::compute_phi_nodes(const FunctionBehaviorConstRef function_behavior, const OpVertexSet& instructions,
1111  var_pp_functorConstRef variableFunctor)
1112 {
1114  const BBGraphConstRef bb_domGraph = function_behavior->CGetBBGraph(FunctionBehavior::DOM_TREE);
1115  const BBGraphConstRef bb_fcfgGraph = function_behavior->CGetBBGraph(FunctionBehavior::FBB);
1116  const OpGraphConstRef cfgGraph = function_behavior->CGetOpGraph(FunctionBehavior::FCFG);
1117  CustomSet<unsigned int> phi_instructions;
1118  for(const auto instruction : instructions)
1119  {
1120  if(GET_TYPE(cfgGraph, instruction) & TYPE_PHI)
1121  {
1122  phi_instructions.insert(cfgGraph->CGetOpNodeInfo(instruction)->GetNodeId());
1123  }
1124  }
1125  if(!phi_instructions.empty())
1126  {
1127  std::map<unsigned int, unsigned int> created_variables;
1128  std::map<unsigned int, std::string> symbol_table;
1129  std::map<unsigned int, std::deque<std::string>> array_of_stacks;
1130  insert_copies(bb_domGraph->CGetBBGraphInfo()->entry_vertex, bb_domGraph, bb_fcfgGraph, variableFunctor,
1131  phi_instructions, created_variables, symbol_table, array_of_stacks);
1133  if(!created_variables.empty())
1134  {
1135  auto cv_it_end = created_variables.end();
1136  for(auto cv_it = created_variables.begin(); cv_it != cv_it_end; ++cv_it)
1137  {
1138  THROW_ASSERT(symbol_table.find(cv_it->first) != symbol_table.end(), "variable not found in symbol_table");
1139  unsigned real_var = cv_it->second;
1141  function_behavior->CGetBehavioralHelper(), real_var, symbol_table[cv_it->first]));
1143  false, false, real_var, phi_functor));
1145  }
1146  }
1147  }
1148 }
1149 
1150 void CWriter::writeRoutineInstructions(const unsigned int function_index, const OpVertexSet& instructions,
1151  var_pp_functorConstRef variableFunctor, vertex bb_start,
1152  CustomOrderedSet<vertex> bb_end)
1153 {
1154  bb_label_counter++;
1155  const auto function_behavior = HLSMgr->CGetFunctionBehavior(function_index);
1156  const auto BH = function_behavior->CGetBehavioralHelper();
1157  const auto cfgGraph = function_behavior->CGetOpGraph(FunctionBehavior::FCFG);
1158  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->CWriter::writeRoutineInstructions - Start");
1159  if(instructions.empty())
1160  {
1162  "<--CWriter::writeRoutineInstructions - instructions is an empty set");
1163  return;
1164  }
1165  else if(instructions.size() == 1)
1166  {
1167  if(GET_TYPE(cfgGraph, (*instructions.begin())) & TYPE_ENTRY)
1168  {
1170  "<--CWriter::writeRoutineInstructions - instructions is a set with only entry");
1171  return;
1172  }
1173  }
1174  const auto bb_fcfgGraph = function_behavior->CGetBBGraph(FunctionBehavior::FBB);
1176  basic_blocks_labels.clear();
1177  VertexIterator vi, vi_end;
1178  vertex bbentry;
1179  CustomOrderedSet<vertex> bb_exit;
1180 
1181  if(!bb_start)
1182  {
1183  bbentry = bb_fcfgGraph->CGetBBGraphInfo()->entry_vertex;
1184  }
1185  else
1186  {
1187  bbentry = bb_start;
1188  }
1189 
1190  if(bb_end.empty())
1191  {
1192  bb_exit.insert(bb_fcfgGraph->CGetBBGraphInfo()->exit_vertex);
1193  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "There are " + STR(bb_exit.size()) + " exit basic blocks");
1194  }
1195  else
1196  {
1197  bb_exit = bb_end;
1198  }
1199 
1200  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Computing labels");
1201  for(boost::tie(vi, vi_end) = boost::vertices(*bb_fcfgGraph); vi != vi_end; vi++)
1202  {
1203  size_t delta = bb_exit.count(*vi) ? 1u : 0u;
1204  if(boost::in_degree(*vi, *bb_fcfgGraph) <= (1 + delta))
1205  {
1207  "---Skipped BB" + STR(bb_fcfgGraph->CGetBBNodeInfo(*vi)->block->number));
1208  continue;
1209  }
1210  const auto bb_node_info = bb_fcfgGraph->CGetBBNodeInfo(*vi);
1211  const unsigned int le = BH->start_with_a_label(bb_node_info->block);
1212  basic_blocks_labels[bb_node_info->block->number] =
1213  (le ? BH->get_label_name(le) :
1214  ("BB_LABEL_" + STR(bb_node_info->block->number)) +
1215  (bb_label_counter == 1 ? "" : "_" + STR(bb_label_counter)));
1217  "---Label of BB" + STR(bb_fcfgGraph->CGetBBNodeInfo(*vi)->block->number) + " is " +
1218  basic_blocks_labels[bb_node_info->block->number]);
1219  }
1220  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Computed labels");
1222  bb_analyzed.clear();
1223  bb_analyzed.insert(bb_exit.begin(), bb_exit.end());
1225  goto_list.clear();
1227  bb_frontier.clear();
1228  bb_frontier.insert(bb_exit.begin(), bb_exit.end());
1229  local_rec_variableFunctor = variableFunctor;
1230  local_rec_function_behavior = function_behavior;
1231  local_rec_instructions.clear();
1232  local_rec_instructions.insert(instructions.begin(), instructions.end());
1238 
1240  writeRoutineInstructions_rec(bbentry, false, function_index);
1241  if(!bb_start && bb_end.size() == 0)
1242  {
1243  OutEdgeIterator oE, oEEnd;
1244  for(boost::tie(oE, oEEnd) = boost::out_edges(bbentry, *bb_fcfgGraph); oE != oEEnd; oE++)
1245  {
1246  if(bb_exit.count(boost::target(*oE, *bb_fcfgGraph)))
1247  {
1248  continue;
1249  }
1250  else
1251  {
1252  writeRoutineInstructions_rec(boost::target(*oE, *bb_fcfgGraph), false, function_index);
1253  }
1254  }
1255  }
1256  CustomOrderedSet<vertex> not_yet_considered;
1257  std::set_difference(goto_list.begin(), goto_list.end(), /*first set*/
1258  bb_analyzed.begin(), bb_analyzed.end(), /*second set*/
1259  std::inserter(not_yet_considered, not_yet_considered.begin()) /*result*/);
1260  while(!not_yet_considered.empty())
1261  {
1262  vertex next_bb = *not_yet_considered.begin();
1263  not_yet_considered.erase(next_bb);
1264  writeRoutineInstructions_rec(next_bb, false, function_index);
1265  not_yet_considered.clear();
1266  std::set_difference(goto_list.begin(), goto_list.end(), /*first set*/
1267  bb_analyzed.begin(), bb_analyzed.end(), /*second set*/
1268  std::inserter(not_yet_considered, not_yet_considered.begin()) /*result*/);
1269  }
1270  const auto& exit = bb_fcfgGraph->CGetBBGraphInfo()->exit_vertex;
1271  if(goto_list.count(exit) && basic_blocks_labels.find(bloc::EXIT_BLOCK_ID) != basic_blocks_labels.end())
1272  {
1274  }
1275  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--CWriter::writeRoutineInstructions - End");
1276 }
1277 
1279  CustomSet<std::string>& locally_declared_types)
1280 {
1281 #ifndef NDEBUG
1282  const auto routine_name = BH->get_function_name();
1283 #endif
1284 
1285  const auto without_transformation = Param->getOption<bool>(OPT_without_transformation);
1286  const auto real_var_type = tree_helper::GetRealType(varType);
1287  const auto type_name = tree_helper::GetTypeName(real_var_type);
1288 
1289  // Check that the variable really needs the declaration of a new type
1291  "-->Declaration of type " + type_name + " (" + GET_CONST_NODE(varType)->ToString() + " - " +
1292  GET_CONST_NODE(real_var_type)->ToString() + ") in function " + routine_name);
1293 
1294  if(!globally_declared_types.count(type_name) && !locally_declared_types.count(type_name))
1295  {
1296  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---This type has not been declared in this function");
1297  locally_declared_types.insert(type_name);
1298  bool is_system;
1299  const auto decl = std::get<0>(tree_helper::GetSourcePath(varType, is_system));
1300  if(!decl.empty() && decl != "<built-in>" && is_system && !tree_helper::IsInLibbambu(varType))
1301  {
1303  "<--Type has not to be declared since it is declared in included " + decl);
1304  return;
1305  }
1306  const auto types_to_be_declared_before =
1307  tree_helper::GetTypesToBeDeclaredBefore(real_var_type, without_transformation);
1308  for(const auto& type_to_be_declared : types_to_be_declared_before)
1309  {
1310  DeclareType(type_to_be_declared, BH, locally_declared_types);
1311  }
1312  if(tree_helper::HasToBeDeclared(TM, real_var_type))
1313  {
1314  if(verbose)
1315  {
1316  indented_output_stream->Append("//declaration of type " + STR(varType) + "(" + STR(real_var_type) + ")\n");
1317  }
1318  indented_output_stream->Append(BH->print_type_declaration(real_var_type->index) + ";\n");
1319  }
1320  const auto types_to_be_declared_after =
1321  tree_helper::GetTypesToBeDeclaredAfter(real_var_type, without_transformation);
1322  for(const auto& type_to_be_declared : types_to_be_declared_after)
1323  {
1324  DeclareType(type_to_be_declared, BH, locally_declared_types);
1325  }
1326  }
1327  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Declared type " + GET_CONST_NODE(varType)->ToString());
1328 }
1329 
1330 void CWriter::DeclareVariable(const tree_nodeConstRef& curVar, CustomSet<unsigned int>& already_declared_variables,
1331  CustomSet<std::string>& locally_declared_types, const BehavioralHelperConstRef& BH,
1332  const var_pp_functorConstRef& varFunc)
1333 {
1334  if(already_declared_variables.count(curVar->index))
1335  {
1336  return;
1337  }
1338  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Declaring variable " + STR(curVar));
1339  already_declared_variables.insert(curVar->index);
1340 
1342  if(BH->GetInit(curVar->index, initVars))
1343  {
1344  for(const auto initVar : initVars)
1345  {
1347  "For variable " + STR(curVar) + " recursing on " + STR(initVar));
1348  if(!already_declared_variables.count(initVar) && !globallyDeclVars.count(initVar))
1349  {
1350  DeclareVariable(TM->CGetTreeReindex(initVar), already_declared_variables, locally_declared_types, BH,
1351  varFunc);
1352  }
1353  }
1354  }
1355  const auto variable_type = tree_helper::CGetType(curVar);
1356  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Type is " + STR(variable_type));
1357  DeclareType(variable_type, BH, locally_declared_types);
1359  {
1360  if(verbose)
1361  {
1362  indented_output_stream->Append("//declaring variable " + STR(curVar) + " - type: " + STR(variable_type) +
1363  "\n");
1364  }
1365  if(GetPointer<const function_decl>(GET_CONST_NODE(curVar)))
1366  {
1367  instrWriter->declareFunction(curVar->index);
1369  }
1370  else
1371  {
1372  indented_output_stream->Append(BH->PrintVarDeclaration(curVar->index, varFunc, true) + ";\n");
1373  }
1374  }
1375  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Declared variable " + STR(curVar));
1376 }
1377 
1379 {
1380  return instrWriter;
1381 }
1382 
1383 void CWriter::writeInclude(const std::string& file_name)
1384 {
1385  if(file_name.find(".h") == std::string::npos || writtenIncludes.find(file_name) != writtenIncludes.end())
1386  {
1387  return;
1388  }
1389  writtenIncludes.insert(file_name);
1390  indented_output_stream->Append("#include \"" + file_name + "\"\n");
1391 }
1392 
1394  CustomSet<unsigned int>& already_declared_variables,
1395  CustomSet<std::string>& already_declared_types, const BehavioralHelperConstRef BH,
1396  const var_pp_functorConstRef varFunc)
1397 {
1398  const auto p = BH->get_parameters();
1399  const auto TreeMan = TM;
1400  const auto is_to_declare = [&p, &TreeMan](unsigned int obj) -> bool {
1401  if(std::find(p.cbegin(), p.cend(), obj) != p.cend())
1402  {
1403  return false;
1404  }
1405  const tree_nodeRef node = TreeMan->get_tree_node_const(obj);
1406  if(node->get_kind() == parm_decl_K)
1407  {
1408  return false;
1409  }
1410  auto* sa = GetPointer<ssa_name>(node);
1411  if(sa && (sa->volatile_flag || (GET_NODE(sa->CGetDefStmt())->get_kind() == gimple_nop_K)) && sa->var &&
1412  (GET_NODE(sa->var)->get_kind() == parm_decl_K))
1413  {
1414  return false;
1415  }
1416  return true;
1417  };
1418 
1419  unsigned int funId = BH->get_function_index();
1420  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->Declaring " + STR(to_be_declared.size()) + " local variables");
1421  for(const auto var : to_be_declared)
1422  {
1423  if(is_to_declare(var))
1424  {
1425  DeclareVariable(TM->CGetTreeReindex(var), already_declared_variables, already_declared_types, BH, varFunc);
1426  }
1427  }
1428  var_pp_functorRef variableFunctor(new std_var_pp_functor(BH));
1429  const FunctionBehaviorConstRef function_behavior = HLSMgr->CGetFunctionBehavior(funId);
1430  const OpGraphConstRef data = function_behavior->CGetOpGraph(FunctionBehavior::DFG);
1431  OpVertexSet vertices = OpVertexSet(data);
1432  VertexIterator v, vEnd;
1433  for(boost::tie(v, vEnd) = boost::vertices(*data); v != vEnd; v++)
1434  {
1435  vertices.insert(*v);
1436  }
1437  THROW_ASSERT(vertices.size() > 0, "Graph for function " + BH->get_function_name() + " is empty");
1438  compute_phi_nodes(function_behavior, vertices, variableFunctor);
1439  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Declaring local variables");
1440 }
1441 
1442 void CWriter::insert_copies(vertex b, const BBGraphConstRef bb_domGraph, const BBGraphConstRef bb_fcfgGraph,
1443  var_pp_functorConstRef variableFunctor, const CustomSet<unsigned int>& phi_instructions,
1444  std::map<unsigned int, unsigned int>& created_variables,
1445  std::map<unsigned int, std::string>& symbol_table,
1446  std::map<unsigned int, std::deque<std::string>>& array_of_stacks)
1447 {
1448  std::list<unsigned int> pushed;
1450  for(const auto& aos : array_of_stacks)
1451  {
1452  if(!aos.second.empty())
1453  {
1454  renaming_table[b][aos.first] = aos.second.back();
1455  symbol_table[aos.first] = aos.second.back();
1456  }
1457  }
1458  schedule_copies(b, bb_domGraph, bb_fcfgGraph, variableFunctor, phi_instructions, created_variables, symbol_table,
1459  pushed, array_of_stacks);
1460  OutEdgeIterator oi, oend;
1461  for(boost::tie(oi, oend) = boost::out_edges(b, *bb_domGraph); oi != oend; ++oi)
1462  {
1463  vertex c = boost::target(*oi, *bb_domGraph);
1464  insert_copies(c, bb_domGraph, bb_fcfgGraph, variableFunctor, phi_instructions, created_variables, symbol_table,
1465  array_of_stacks);
1466  }
1467  pop_stack(pushed, array_of_stacks);
1468 }
1469 
1470 void CWriter::schedule_copies(vertex b, const BBGraphConstRef bb_domGraph, const BBGraphConstRef bb_fcfgGraph,
1471  var_pp_functorConstRef variableFunctor, const CustomSet<unsigned int>& phi_instructions,
1472  std::map<unsigned int, unsigned int>& created_variables,
1473  std::map<unsigned int, std::string>& symbol_table, std::list<unsigned int>& pushed,
1474  std::map<unsigned int, std::deque<std::string>>& array_of_stacks)
1475 {
1477  const BBNodeInfoConstRef bb_node_info = bb_fcfgGraph->CGetBBNodeInfo(b);
1478  unsigned int bi_id = bb_node_info->block->number;
1479 
1480  TreeNodesPairSet copy_set, worklist;
1481  std::map<unsigned int, unsigned int> map;
1482  CustomOrderedSet<unsigned int> used_by_another;
1483  std::map<unsigned int, unsigned int> bb_dest_definition;
1484  OutEdgeIterator oi, oend;
1485  for(boost::tie(oi, oend) = boost::out_edges(b, *bb_fcfgGraph); oi != oend; ++oi)
1486  {
1487  vertex s = boost::target(*oi, *bb_fcfgGraph);
1488  const BBNodeInfoConstRef si = bb_fcfgGraph->CGetBBNodeInfo(s);
1489  for(const auto& phi_op : si->block->CGetPhiList())
1490  {
1491  if(phi_instructions.find(GET_INDEX_NODE(phi_op)) == phi_instructions.end())
1492  {
1493  continue;
1494  }
1495  auto* pn = GetPointer<gimple_phi>(GET_NODE(phi_op));
1496  tree_nodeRef dest = pn->res;
1497  unsigned int dest_i = GET_INDEX_NODE(pn->res);
1498  bool is_virtual = pn->virtual_flag;
1499  if(!is_virtual)
1500  {
1501  bb_dest_definition[dest_i] = si->block->number;
1502  for(const auto& def_edge : pn->CGetDefEdgesList())
1503  {
1504  if(def_edge.second == bi_id)
1505  {
1506  tree_nodeRef src = def_edge.first;
1507  unsigned int src_i = GET_INDEX_NODE(def_edge.first);
1508  copy_set.insert(std::pair<tree_nodeRef, tree_nodeRef>(src, dest));
1509  map[src_i] = src_i;
1510  map[dest_i] = dest_i;
1511  used_by_another.insert(src_i);
1512  break;
1513  }
1514  }
1515  }
1516  }
1517  }
1518 
1520  for(auto cs_it = copy_set.begin(); cs_it != copy_set.end();)
1521  {
1522  auto current_it = cs_it;
1523  ++cs_it;
1524  if(used_by_another.find(GET_INDEX_NODE(current_it->second)) == used_by_another.end())
1525  {
1526  worklist.insert(*current_it);
1527  copy_set.erase(current_it);
1528  }
1529  }
1530 
1532  while(!worklist.empty() || !copy_set.empty())
1533  {
1534  TreeNodesPairSet worklist_restart;
1535  do
1536  {
1537  for(auto& wl : worklist)
1538  {
1539  tree_nodeRef src = GET_NODE(wl.first);
1540  unsigned int src_i = GET_INDEX_NODE(wl.first);
1541  unsigned int dest_i = GET_INDEX_NODE(wl.second);
1545  // if(boost::out_degree(b, *bb_domGraph) > 0 &&
1546  // bb_node_info->block->live_out.find(dest_i) != bb_node_info->block->live_out.end()
1547  // )
1548  bool add_copy = false;
1549  OutEdgeIterator o_it, o_it_end;
1550  for(boost::tie(o_it, o_it_end) = boost::out_edges(b, *bb_domGraph); o_it != o_it_end; ++o_it)
1551  {
1552  vertex tgt_bb = boost::target(*o_it, *bb_domGraph);
1553  if(tgt_bb == b)
1554  {
1555  continue;
1556  }
1557  const BBNodeInfoConstRef tgt_bi = bb_domGraph->CGetBBNodeInfo(tgt_bb);
1558  if(tgt_bi && tgt_bi->block->live_in.find(dest_i) != tgt_bi->block->live_in.end())
1559  {
1560  add_copy = true;
1561  }
1562  }
1563  if(add_copy)
1564  {
1565  // THROW_ERROR("check the source code @" + STR(dest_i));
1567  unsigned int t_i = create_new_identifier(symbol_table);
1568  basic_block_prefix[bb_dest_definition[dest_i]] +=
1569  symbol_table.find(t_i)->second + " = " + (*variableFunctor)(dest_i) + ";\n";
1570  created_variables[t_i] = dest_i;
1571  map[t_i] = t_i;
1573  push_stack(symbol_table.find(t_i)->second, dest_i, pushed, array_of_stacks);
1574  renaming_table[b][dest_i] = symbol_table.find(t_i)->second;
1575  }
1577  std::string copy_statement;
1578  if(symbol_table.find(map.find(src_i)->second) != symbol_table.end())
1579  {
1580  copy_statement +=
1581  (*variableFunctor)(dest_i) + " = " + symbol_table.find(map.find(src_i)->second)->second + ";\n";
1582  }
1583  else if(dest_i != map.find(src_i)->second)
1584  {
1585  copy_statement +=
1586  (*variableFunctor)(dest_i) + " = " + (*variableFunctor)(map.find(src_i)->second) + ";\n";
1587  }
1588 
1589  basic_block_tail[bi_id] += copy_statement;
1590  // map[src_i] = dest_i;
1591 
1592  for(auto cs1_it = copy_set.begin(); cs1_it != copy_set.end();)
1593  {
1594  auto current1_it = cs1_it;
1595  ++cs1_it;
1596  if(src == current1_it->second)
1597  {
1598  worklist_restart.insert(*current1_it);
1599  copy_set.erase(current1_it);
1600  }
1601  }
1602  }
1603  worklist = worklist_restart;
1604  worklist_restart.clear();
1605  } while(!worklist.empty());
1606 
1607  auto cs2_it_end = copy_set.end();
1608  auto cs2_it = copy_set.begin();
1609  if(cs2_it != cs2_it_end)
1610  {
1611  auto current2_it = cs2_it;
1612  unsigned int dest_i = GET_INDEX_NODE(current2_it->second);
1615  ++cs2_it;
1616  bool add_temporary = false;
1617  for(; cs2_it != cs2_it_end; ++cs2_it)
1618  {
1619  if(GET_INDEX_NODE(cs2_it->first) == dest_i)
1620  {
1621  add_temporary = true;
1622  break;
1623  }
1624  }
1625  if(add_temporary)
1626  {
1628  unsigned int t_i = create_new_identifier(symbol_table);
1630  basic_block_tail[bi_id] += symbol_table.find(t_i)->second + " = " + (*variableFunctor)(dest_i) + ";\n";
1631  created_variables[t_i] = dest_i;
1632  map[t_i] = t_i;
1633  map[dest_i] = t_i;
1634  }
1635  worklist.insert(*current2_it);
1636  copy_set.erase(current2_it);
1637  }
1638  }
1639 }
1640 
1641 unsigned int CWriter::create_new_identifier(std::map<unsigned int, std::string>& symbol_table)
1642 {
1643  unsigned int counter = 0;
1644  unsigned int node_id_this = 0;
1645  std::string new_name;
1646  do
1647  {
1648  new_name = "__t__" + STR(fake_max_tree_node_id) + "_" + STR(counter);
1649  node_id_this = TM->find_identifier_nodeID(new_name);
1650  counter++;
1651  } while(node_id_this > 0);
1652  symbol_table[fake_max_tree_node_id] = new_name;
1653  node_id_this = fake_max_tree_node_id;
1655  return node_id_this;
1656 }
1657 
1658 void CWriter::push_stack(std::string symbol_name, unsigned int dest_i, std::list<unsigned int>& pushed,
1659  std::map<unsigned int, std::deque<std::string>>& array_of_stacks)
1660 {
1661  THROW_ASSERT(std::find(pushed.begin(), pushed.end(), dest_i) == pushed.end(), "multiple push is not allowed");
1662  array_of_stacks[dest_i].push_back(symbol_name);
1663  pushed.push_back(dest_i);
1664 }
1665 
1666 void CWriter::pop_stack(std::list<unsigned int>& pushed,
1667  std::map<unsigned int, std::deque<std::string>>& array_of_stacks)
1668 {
1669  for(auto var_id : pushed)
1670  {
1671  THROW_ASSERT(array_of_stacks.find(var_id) != array_of_stacks.end(), "the array of stacks is inconsistent");
1672  THROW_ASSERT(!array_of_stacks.find(var_id)->second.empty(), "the variable is not mapped");
1673  array_of_stacks.find(var_id)->second.pop_back();
1674  }
1675  pushed.clear();
1676 }
1677 
1679 {
1680  indented_output_stream->Append("#define NIL(type) ((type *) 0)\n");
1681  indented_output_stream->Append("typedef struct st_table_entry st_table_entry;\n");
1682  indented_output_stream->Append("struct st_table_entry\n");
1684  indented_output_stream->Append("unsigned long long key;\n");
1685  indented_output_stream->Append("unsigned long long record;\n");
1686  indented_output_stream->Append("st_table_entry *next;\n");
1687  indented_output_stream->Append("};\n");
1689  indented_output_stream->Append("typedef struct st_table st_table;\n");
1690  indented_output_stream->Append("struct st_table\n");
1692  indented_output_stream->Append("int num_bins;\n");
1693  indented_output_stream->Append("int num_entries;\n");
1694  indented_output_stream->Append("int max_density;\n");
1695  indented_output_stream->Append("int reorder_flag;\n");
1696  indented_output_stream->Append("double grow_factor;\n");
1697  indented_output_stream->Append("st_table_entry **bins;\n");
1698  indented_output_stream->Append("};\n");
1699  indented_output_stream->Append("typedef struct st_generator st_generator;\n");
1700  indented_output_stream->Append("struct st_generator\n");
1702  indented_output_stream->Append("st_table *table;\n");
1703  indented_output_stream->Append("st_table_entry *entry;\n");
1704  indented_output_stream->Append("int index;\n");
1705  indented_output_stream->Append("};\n");
1706  indented_output_stream->Append("#define ST_DEFAULT_MAX_DENSITY 5\n");
1707  indented_output_stream->Append("#define ST_DEFAULT_INIT_TABLE_SIZE 11\n");
1708  indented_output_stream->Append("#define ST_DEFAULT_GROW_FACTOR 2.0\n");
1709  indented_output_stream->Append("#define ST_DEFAULT_REORDER_FLAG 0\n");
1710  indented_output_stream->Append("#define ST_OUT_OF_MEM -10000\n");
1711  indented_output_stream->Append("#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)\n");
1712  indented_output_stream->Append("#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))\n");
1713  indented_output_stream->Append("#if SIZEOF_VOID_P == 8\n");
1714  indented_output_stream->Append("#define st_shift 3\n");
1715  indented_output_stream->Append("#else\n");
1716  indented_output_stream->Append("#define st_shift 2\n");
1717  indented_output_stream->Append("#endif\n");
1718  indented_output_stream->Append("#define ST_PTRHASH(x,size) ((unsigned int)((unsigned long)(x)>>st_shift)%size)\n");
1720  indented_output_stream->Append("static int rehash(st_table *table)\n");
1722  indented_output_stream->Append("st_table_entry *ptr, *next, **old_bins;\n");
1723  indented_output_stream->Append("int i, old_num_bins, hash_val, old_num_entries;\n");
1724  indented_output_stream->Append("/* save old values */\n");
1725  indented_output_stream->Append("old_bins = table->bins;\n");
1726  indented_output_stream->Append("old_num_bins = table->num_bins;\n");
1727  indented_output_stream->Append("old_num_entries = table->num_entries;\n");
1728  indented_output_stream->Append("/* rehash */\n");
1729  indented_output_stream->Append("table->num_bins = (int) (table->grow_factor * old_num_bins);\n");
1730  indented_output_stream->Append("if (table->num_bins % 2 == 0)\n");
1732  indented_output_stream->Append("table->num_bins += 1;\n");
1734  indented_output_stream->Append("table->num_entries = 0;\n");
1735  indented_output_stream->Append("table->bins = ALLOC(st_table_entry *, table->num_bins);\n");
1736  indented_output_stream->Append("if (table->bins == NIL(st_table_entry *))\n");
1738  indented_output_stream->Append("table->bins = old_bins;\n");
1739  indented_output_stream->Append("table->num_bins = old_num_bins;\n");
1740  indented_output_stream->Append("table->num_entries = old_num_entries;\n");
1741  indented_output_stream->Append("return ST_OUT_OF_MEM;\n");
1743  indented_output_stream->Append("/* initialize */\n");
1744  indented_output_stream->Append("for (i = 0; i < table->num_bins; i++)\n");
1746  indented_output_stream->Append("table->bins[i] = 0;\n");
1748  indented_output_stream->Append("/* copy data over */\n");
1749  indented_output_stream->Append("for (i = 0; i < old_num_bins; i++)\n");
1751  indented_output_stream->Append("ptr = old_bins[i];\n");
1752  indented_output_stream->Append("while (ptr != NIL(st_table_entry))\n");
1754  indented_output_stream->Append("next = ptr->next;\n");
1755  indented_output_stream->Append("hash_val = ptr->key%table->num_bins;\n");
1756  indented_output_stream->Append("ptr->next = table->bins[hash_val];\n");
1757  indented_output_stream->Append("table->bins[hash_val] = ptr;\n");
1758  indented_output_stream->Append("table->num_entries++;\n");
1759  indented_output_stream->Append("ptr = next;\n");
1762  indented_output_stream->Append("FREE(old_bins);\n");
1763  indented_output_stream->Append("return 1;\n");
1764  indented_output_stream->Append("} /* rehash */\n");
1766  indented_output_stream->Append("st_table * st_init_table_with_params(\n");
1767  indented_output_stream->Append("int size,\n");
1768  indented_output_stream->Append("int density,\n");
1769  indented_output_stream->Append("double grow_factor,\n");
1770  indented_output_stream->Append("int reorder_flag)\n");
1772  indented_output_stream->Append("int i;\n");
1773  indented_output_stream->Append("st_table *newt;\n");
1774  indented_output_stream->Append("newt = ALLOC(st_table, 1);\n");
1775  indented_output_stream->Append("if (newt == NIL(st_table)) \n");
1777  indented_output_stream->Append("return NIL(st_table);\n");
1779  indented_output_stream->Append("newt->num_entries = 0;\n");
1780  indented_output_stream->Append("newt->max_density = density;\n");
1781  indented_output_stream->Append("newt->grow_factor = grow_factor;\n");
1782  indented_output_stream->Append("newt->reorder_flag = reorder_flag;\n");
1783  indented_output_stream->Append("if (size <= 0)\n");
1785  indented_output_stream->Append("size = 1;\n");
1787  indented_output_stream->Append("newt->num_bins = size;\n");
1788  indented_output_stream->Append("newt->bins = ALLOC(st_table_entry *, size);\n");
1789  indented_output_stream->Append("if (newt->bins == NIL(st_table_entry *))\n");
1791  indented_output_stream->Append("FREE(newt);\n");
1792  indented_output_stream->Append("return NIL(st_table);\n");
1794  indented_output_stream->Append("for(i = 0; i < size; i++)\n");
1796  indented_output_stream->Append("newt->bins[i] = 0;\n");
1798  indented_output_stream->Append("return newt;\n");
1799  indented_output_stream->Append("} /* st_init_table_with_params */\n");
1801  indented_output_stream->Append("st_table * st_init_table()\n");
1803  indented_output_stream->Append("return st_init_table_with_params(ST_DEFAULT_INIT_TABLE_SIZE,\n");
1804  indented_output_stream->Append("ST_DEFAULT_MAX_DENSITY,\n");
1805  indented_output_stream->Append("ST_DEFAULT_GROW_FACTOR,\n");
1806  indented_output_stream->Append("ST_DEFAULT_REORDER_FLAG);\n");
1807  indented_output_stream->Append("} /* st_init_table */\n");
1809  indented_output_stream->Append("st_generator *\n");
1810  indented_output_stream->Append("st_init_gen(st_table *table)\n");
1812  indented_output_stream->Append("st_generator *gen;\n");
1813  indented_output_stream->Append("gen = ALLOC(st_generator, 1);\n");
1814  indented_output_stream->Append("if (gen == NIL(st_generator))\n");
1816  indented_output_stream->Append("return NIL(st_generator);\n");
1818  indented_output_stream->Append("gen->table = table;\n");
1819  indented_output_stream->Append("gen->entry = NIL(st_table_entry);\n");
1820  indented_output_stream->Append("gen->index = 0;\n");
1821  indented_output_stream->Append("return gen;\n");
1822  indented_output_stream->Append("} /* st_init_gen */\n");
1825  "int st_gen_int(st_generator *gen, unsigned long long * key_p, unsigned long long * value_p)\n");
1827  indented_output_stream->Append("int i;\n");
1828  indented_output_stream->Append("if (gen->entry == NIL(st_table_entry))\n");
1830  indented_output_stream->Append("/* try to find next entry */\n");
1831  indented_output_stream->Append("for(i = gen->index; i < gen->table->num_bins; i++)\n");
1833  indented_output_stream->Append("if (gen->table->bins[i] != NIL(st_table_entry))\n");
1835  indented_output_stream->Append("gen->index = i+1;\n");
1836  indented_output_stream->Append("gen->entry = gen->table->bins[i];\n");
1837  indented_output_stream->Append("break;\n");
1840  indented_output_stream->Append("if (gen->entry == NIL(st_table_entry))\n");
1842  indented_output_stream->Append("return 0; /* that's all folks ! */\n");
1845  indented_output_stream->Append("*key_p = gen->entry->key;\n");
1846  indented_output_stream->Append("if (value_p != NIL(unsigned long long))\n");
1848  indented_output_stream->Append("*value_p = gen->entry->record;\n");
1850  indented_output_stream->Append("gen->entry = gen->entry->next;\n");
1851  indented_output_stream->Append("return 1;\n");
1852  indented_output_stream->Append("} /* st_gen_int */\n");
1854  indented_output_stream->Append("void st_free_gen(st_generator *gen)\n");
1856  indented_output_stream->Append("FREE(gen);\n");
1857  indented_output_stream->Append("} /* st_free_gen */\n");
1860  "int st_find_or_add(st_table *table, unsigned long long key, unsigned long long ** slot)\n");
1862  indented_output_stream->Append("int hash_val;\n");
1863  indented_output_stream->Append("st_table_entry *newt, *ptr, **last;\n");
1864  indented_output_stream->Append("hash_val = key%table->num_bins;\n");
1865  indented_output_stream->Append("last = &(table)->bins[hash_val];\n");
1866  indented_output_stream->Append("ptr = *(last);\n");
1867  indented_output_stream->Append("while (ptr != NIL(st_table_entry) && ptr->key != key)\n");
1869  indented_output_stream->Append("last = &(ptr)->next;\n");
1870  indented_output_stream->Append("ptr = *(last);\n");
1872  indented_output_stream->Append("if (ptr != NIL(st_table_entry) && (table)->reorder_flag)\n");
1874  indented_output_stream->Append("*(last) = (ptr)->next;\n");
1875  indented_output_stream->Append("(ptr)->next = (table)->bins[hash_val];\n");
1876  indented_output_stream->Append("(table)->bins[hash_val] = (ptr);\n");
1878  indented_output_stream->Append("if (ptr == NIL(st_table_entry)) \n");
1880  indented_output_stream->Append("if (table->num_entries / table->num_bins >= table->max_density) \n");
1882  indented_output_stream->Append("if (rehash(table) == ST_OUT_OF_MEM) \n");
1884  indented_output_stream->Append("return ST_OUT_OF_MEM;\n");
1886  indented_output_stream->Append("hash_val = key%table->num_bins;\n");
1888  indented_output_stream->Append("newt = ALLOC(st_table_entry, 1);\n");
1889  indented_output_stream->Append("if (newt == NIL(st_table_entry)) \n");
1891  indented_output_stream->Append("return ST_OUT_OF_MEM;\n");
1893  indented_output_stream->Append("newt->key = key;\n");
1894  indented_output_stream->Append("newt->record = 0;\n");
1895  indented_output_stream->Append("newt->next = table->bins[hash_val];\n");
1896  indented_output_stream->Append("table->bins[hash_val] = newt;\n");
1897  indented_output_stream->Append("table->num_entries++;\n");
1898  indented_output_stream->Append("if (slot != NIL(void)) \n");
1899  indented_output_stream->Append("*slot = &newt->record;\n");
1900  indented_output_stream->Append("return 0;\n");
1902  indented_output_stream->Append("else\n");
1904  indented_output_stream->Append("if (slot != NIL(void)) \n");
1905  indented_output_stream->Append("*slot = &ptr->record;\n");
1906  indented_output_stream->Append("return 1;\n");
1908  indented_output_stream->Append("} /* st_find_or_add */\n");
1909  indented_output_stream->Append("#define st_foreach_item_int(table, gen, key, value) for(gen=st_init_gen(table); "
1910  "st_gen_int(gen,key,value) || (st_free_gen(gen),0);)\n");
1911 }
1912 
1913 void CWriter::WriteFile(const std::string& file_name)
1914 {
1915  indented_output_stream->WriteFile(file_name);
1916 }
1917 
1918 void CWriter::WriteBBHeader(const unsigned int, const unsigned int)
1919 {
1920 }
1921 
1923 {
1924  indented_output_stream->Append("void " + STR(BUILTIN_WAIT_CALL) + "(void * ptr, ...)\n");
1926  indented_output_stream->Append("va_list ap;\n");
1927  indented_output_stream->Append("va_start(ap, ptr);\n");
1928  indented_output_stream->Append("int boolReturn = va_arg(ap, int);\n");
1929  for(const unsigned int id : HLSMgr->CGetCallGraphManager()->GetAddressedFunctions())
1930  {
1931  const auto BH = HLSMgr->CGetFunctionBehavior(id)->CGetBehavioralHelper();
1932  indented_output_stream->Append("if (ptr == " + BH->get_function_name() + ")\n");
1934  std::vector<std::pair<std::string, std::string>> typeAndName;
1935  for(const auto& I : BH->GetParameters())
1936  {
1937  const auto type_node = tree_helper::CGetType(I);
1938  const auto type_size = tree_helper::Size(type_node);
1941  {
1942  if(type_size < 32)
1943  {
1944  type = "int";
1945  }
1946  }
1948  {
1949  if(type_size < 32)
1950  {
1951  type = "unsigned int";
1952  }
1953  }
1955  {
1956  if(type_size < 64)
1957  {
1958  type = "double";
1959  }
1960  }
1961  const auto name = BH->PrintVariable(I->index);
1962  typeAndName.push_back(std::make_pair(type, name));
1963  }
1964  for(const auto& I : typeAndName)
1965  {
1966  indented_output_stream->Append(I.first + " " + I.second + " = va_arg(ap, " + I.first + ");\n");
1967  }
1968  const auto returnType_node = tree_helper::GetFunctionReturnType(TM->CGetTreeReindex(id));
1969  std::string returnType;
1970  if(returnType_node)
1971  {
1972  const auto returnType_size = tree_helper::Size(returnType_node);
1973  returnType = tree_helper::PrintType(TM, returnType_node);
1974  if(tree_helper::IsSignedIntegerType(returnType_node))
1975  {
1976  if(returnType_size < 32)
1977  {
1978  returnType = "int";
1979  }
1980  }
1981  else if(tree_helper::IsUnsignedIntegerType(returnType_node))
1982  {
1983  if(returnType_size < 32)
1984  {
1985  returnType = "unsigned int";
1986  }
1987  }
1988  else if(tree_helper::IsRealType(returnType_node))
1989  {
1990  if(returnType_size < 64)
1991  {
1992  returnType = "double";
1993  }
1994  }
1995  }
1996  else
1997  {
1998  returnType = "void";
1999  }
2000  if(returnType != "void")
2001  {
2002  indented_output_stream->Append(returnType + " res = ");
2003  }
2004  indented_output_stream->Append(BH->get_function_name() + "(");
2005  const auto typeAndNameSize = typeAndName.size();
2006  if(typeAndNameSize)
2007  {
2008  for(size_t i = 0; i < typeAndNameSize - 1; ++i)
2009  {
2010  indented_output_stream->Append(typeAndName[i].second + ",");
2011  }
2012  indented_output_stream->Append(typeAndName[typeAndNameSize - 1].second);
2013  }
2014  indented_output_stream->Append(");\n");
2015  if(returnType != "void")
2016  {
2017  indented_output_stream->Append("if (boolReturn) {\n");
2018  indented_output_stream->Append(returnType + "* " + "resultAddress = va_arg(ap, " + returnType + " *);\n");
2019  indented_output_stream->Append("*resultAddress = res;\n");
2021  }
2023  }
2024  indented_output_stream->Append("va_end(ap);\n");
2025  indented_output_stream->Append("}\n\n");
2026 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
OpGraphConstRef local_rec_cfgGraph
Definition: c_writer.hpp:148
#define TYPE_SWITCH
constant identifying the node type of a SWITCH operation.
Definition: op_graph.hpp:105
std::string PrintVarDeclaration(unsigned int var, const var_pp_functorConstRef vppf, bool init_has_to_be_printed) const
This function prints the declaration of a variable without the closing ";".
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
int GetSelector() const
Return the selector of this graph.
Definition: graph.hpp:922
Vertex get_immediate_dominator(Vertex v) const
Return the immediate dominator of a Vertex.
Definition: Dominance.hpp:757
Data structure representing the entire HLS information.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
Factory class to create c backend.
boost::graph_traits< graph >::out_edge_iterator OutEdgeIterator
out_edge_iterator definition.
Definition: graph.hpp:1312
#define GET_TYPE(data, vertex_index)
Helper macro returning the type associated with a node.
const dominance< BBGraph > * dominators
Definition: c_writer.hpp:145
CustomOrderedSet< vertex > goto_list
Definition: c_writer.hpp:141
void WriteFile(const std::string &file_name)
Write the indented output on a file.
static void clear_renaming_table()
remove all the entries from the renaming table
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
static std::set< tree_nodeConstRef, TreeNodeConstSorter > GetTypesToBeDeclaredAfter(const tree_nodeConstRef &tn, const bool without_transformation)
Return the types to be declared after declaring index type.
#define TYPE_MULTIIF
constant identifying the a multi-way if
Definition: op_graph.hpp:202
#define TYPE_VPHI
constant string identifying an operation node of type virtual phi-nodes
Definition: op_graph.hpp:162
string target
Definition: lenet_tvm.py:16
const tree_nodeRef CGetTreeReindex(const unsigned int i) const
Return a tree_reindex wrapping the i-th tree_node.
std::string get_function_name() const
Return the name of the function.
virtual unsigned int end_with_a_cond_or_goto(const blocRef &block) const
Return the nodeID of the last statement of a basic block in case that statement is a cond or a goto e...
int debug_level
the debug level
Definition: c_writer.hpp:122
#define TYPE_IF
constant identifying the node type of an IF operation.
Definition: op_graph.hpp:100
Definition of the class representing a generic C application.
const dominance< BBGraph > * post_dominators
Definition: c_writer.hpp:146
virtual void Initialize()
Initialize data structure.
Definition: c_writer.cpp:228
static std::string print_type(const tree_managerConstRef &TM, unsigned int type, bool global=false, bool print_qualifiers=false, bool print_storage=false, unsigned int var=0, const var_pp_functorConstRef &vppf=var_pp_functorConstRef(), const std::string &prefix="", const std::string &tail="")
Print a type and its variable in case var is not zero.
const CustomSet< unsigned int > GetLocalVariables(const unsigned int function_id) const
Compute the local variables of a function.
Definition: c_writer.cpp:356
const BBGraphInfoConstRef CGetBBGraphInfo() const
Returns the property associated with the graph.
CustomOrderedSet< vertex > bb_frontier
Definition: c_writer.hpp:138
virtual void WriteBBHeader(const unsigned int bb_number, const unsigned int function_index)
Definition: c_writer.cpp:1918
void WriteHashTableImplementation()
Write the implementation of a hash table with long long int as key and long long int as value...
Definition: c_writer.cpp:1678
#define GET_NAME(data, vertex_index)
Helper macro returning the name associated with a node.
unsigned int get_next_available_tree_node_id() const
return the next available tree node id.
CustomSet< unsigned int > globallyDeclVars
Definition: c_writer.hpp:106
boost::graph_traits< graph >::in_edge_iterator InEdgeIterator
in_edge_iterator definition.
Definition: graph.hpp:1310
unsigned int get_function_index() const
Return the index of the function.
Class to print indented code.
Simple class to print single instruction.
#define BUILTIN_WAIT_CALL
constant defining the builtin wait call intrinsic function
Definition: op_graph.hpp:358
Definition of hash function for EdgeDescriptor.
Definition: graph.hpp:1321
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
bool verbose
Verbosity means that a comment is printed for each line in the output file.
Definition: c_writer.hpp:116
#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
#define TYPE_INIT
Constant string identifying an operation that is a variable initialization.
Definition: op_graph.hpp:167
void push_stack(std::string symbol_name, unsigned int dest_i, std::list< unsigned int > &pushed, std::map< unsigned int, std::deque< std::string >> &array_of_stacks)
push on the stack of temporary variables that has to replaced
Definition: c_writer.cpp:1658
Simple class to print single instruction.
const tree_managerConstRef TM
The tree manager.
Definition: c_writer.hpp:98
void pop_stack(std::list< unsigned int > &pushed, std::map< unsigned int, std::deque< std::string >> &array_of_stacks)
remove from the stack all the temporaries
Definition: c_writer.cpp:1666
Data structure describing a basic block at tree level.
static unsigned int get_type_index(const tree_managerConstRef &TM, const unsigned int index, long long int &vec_size, bool &is_a_pointer, bool &is_a_function)
Return the treenode index of the type of index.
dominance< BBGraph > * post_dominators
This class stores post-dominator information.
Base class to pass information to a c backend.
A set of operation vertices.
Definition: op_graph.hpp:654
static bool IsInLibbambu(const tree_managerConstRef &TM, const unsigned int index)
Return true if the decl node or type is in libbambu.
virtual void WriteFunctionDeclaration(const unsigned int funId)
Writes the declaration of the function whose id in the tree is funId.
Definition: c_writer.cpp:372
#define TYPE_PHI
constant string identifying an operation node of type PHI
Definition: op_graph.hpp:135
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
Simple class used to drive the backend in order to be able to print c source code.
A set of const tree node.
Definition: tree_node.hpp:267
#define STR(s)
Macro which performs a lexical_cast to a string.
#define FB_CFG_SELECTOR
Feedback control flow edge selector.
virtual std::string PrintConstant(const tree_nodeConstRef &var, const var_pp_functorConstRef vppf=var_pp_functorConstRef()) const
Print the constant associated with var.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
refcount< CWriter > CWriterRef
Definition: c_writer.hpp:422
static bool HasToBeDeclared(const tree_managerConstRef &TM, const tree_nodeConstRef &type)
Return true if the type has to be declared.
void schedule_copies(vertex b, const BBGraphConstRef bb_domGraph, const BBGraphConstRef bb_fcfgGraph, var_pp_functorConstRef variableFunctor, const CustomSet< unsigned int > &phi_instructions, std::map< unsigned int, unsigned int > &created_variables, std::map< unsigned int, std::string > &symbol_table, std::list< unsigned int > &pushed, std::map< unsigned int, std::deque< std::string >> &array_of_stacks)
insert copies according the algorithm described in Briggs et.
Definition: c_writer.cpp:1470
virtual void WriteFile(const std::string &file_name)
Writes the final C file.
Definition: c_writer.cpp:1913
static bool IsUnsignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of unsigned integer type.
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 TYPE_LABEL
A vertex is of type TYPE_LABEL when it is a target of a goto expression.
Definition: op_graph.hpp:151
static bool IsSignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of integer type.
const OpNodeInfoConstRef CGetOpNodeInfo(const vertex node) const
Returns the info associated with a node.
Definition: op_graph.hpp:843
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
const BBEdgeInfoConstRef CGetBBEdgeInfo(const EdgeDescriptor e) const
Returns the info associated with an edge.
const IndentedOutputStreamRef indented_output_stream
Represents the stream we are currently writing to.
Definition: c_writer.hpp:101
Standard functor that returns the name of a variable.
const std::list< unsigned int > get_parameters() const
Return the list of index of original parameters of the function.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
std::set< Key, Compare, Alloc > OrderedSetStd
Definition: custom_set.hpp:59
virtual void EndFunctionBody(unsigned int funId)
Writes the code necessary to close a function (this function was a function also present in the origi...
Definition: c_writer.cpp:409
static bool IsSystemType(const tree_nodeConstRef &type)
Return true if variable or type is a system one.
unsigned map[NUM_VERTICES]
Definition: bfs.c:12
static std::set< tree_nodeConstRef, TreeNodeConstSorter > GetTypesToBeDeclaredBefore(const tree_nodeConstRef &tn, const bool without_transformation)
Return the types to be declared before declaring index type.
Control flow graph.
const ParameterConstRef Param
set of parameters
Definition: c_writer.hpp:119
virtual unsigned int GetInit(unsigned int var, CustomUnorderedSet< unsigned int > &list_of_variables) const
return the initialization object associated with the variable.
Class use to write the C code with instruented edges for basic blocks profiling.
void Append(const std::string &str)
Append a string to the output.
static std::tuple< std::string, unsigned int, unsigned int > GetSourcePath(const tree_nodeConstRef &node, bool &is_system)
Return where a function or a type is defined.
Basic block dominator tree.
#define default_COND
constant used to represent label "default" of a switch construct
virtual void StartFunctionBody(const unsigned int function_id)
Writes the body of the function to the specified stream.
Definition: c_writer.cpp:384
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 compute_phi_nodes(const FunctionBehaviorConstRef function_behavior, const OpVertexSet &instructions, var_pp_functorConstRef variableFunctor)
Determines the instructions coming out from phi-node splitting.
Definition: c_writer.cpp:1110
CustomSet< std::string > globally_declared_types
This set contains the list of the non built_in types already declared in the global scope...
Definition: c_writer.hpp:104
virtual void DeclareType(const tree_nodeConstRef &varType, const BehavioralHelperConstRef &behavioral_helper, CustomSet< std::string > &locally_declared_type)
This method should be called only if the type associated with the variable is a non built_in type and...
Definition: c_writer.cpp:1278
Basic block control flow graph with feedback.
virtual int unsigned start_with_a_label(const blocRef &block) const
Return the nodeID of the first statement of a basic block in case that statement is a label expressio...
static void rename_a_variable(unsigned int var, const std::string &new_name)
rename a variable
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
Abstract class to write an actor graphs.
CWriter(const HLS_managerConstRef _HLSMgr, const InstructionWriterRef instruction_writer, const IndentedOutputStreamRef indented_output_stream, const ParameterConstRef Param, bool verbose=true)
Constructor of the class.
Definition: c_writer.cpp:140
This file contains the routines necessary to create a C executable program with instrumented edges fo...
#define TYPE_FOR
constant string identifying the node type of an WHILE operation.
Definition: op_graph.hpp:115
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
virtual void DeclareVariable(const tree_nodeConstRef &curVar, CustomSet< unsigned int > &already_declared_variables, CustomSet< std::string > &locally_declared_type, const BehavioralHelperConstRef &behavioral_helper, const var_pp_functorConstRef &varFunc)
Declares the local variable; in case the variable used in the intialization of curVar hasn&#39;t been dec...
Definition: c_writer.cpp:1330
CustomOrderedSet< std::string > writtenIncludes
Definition: c_writer.hpp:191
const BehavioralHelperConstRef CGetBehavioralHelper() const
Returns the helper associated with the function.
boost::graph_traits< graph >::vertex_iterator VertexIterator
vertex_iterator definition.
Definition: graph.hpp:1307
void insert_copies(vertex b, const BBGraphConstRef bb_domGraph, const BBGraphConstRef bb_fcfgGraph, var_pp_functorConstRef variableFunctor, const CustomSet< unsigned int > &phi_instructions, std::map< unsigned int, unsigned int > &created_variables, std::map< unsigned int, std::string > &symbol_table, std::map< unsigned int, std::deque< std::string >> &array_of_stacks)
Compute the copy assignments needed by the phi nodes destruction Further details can be found in: ...
Definition: c_writer.cpp:1442
virtual void WriteBodyLoop(const unsigned int function_index, const unsigned int, vertex current_vertex, bool bracket)
Write the instructions belonging to a body loop.
Definition: c_writer.cpp:238
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
static CWriterRef CreateCWriter(const CBackendInformationConstRef c_backend_information, const HLS_managerConstRef hls_man, const IndentedOutputStreamRef indented_output_stream, const ParameterConstRef parameters, const bool verbose)
Factory method.
Definition: c_writer.cpp:159
std::string PrintVariable(unsigned int var) const
Print the name of the variable associated to the index.
void writeRoutineInstructions_rec(vertex current_vertex, bool bracket, const unsigned int function_index)
Write recursively instructions belonging to a basic block of task or of a function.
Definition: c_writer.cpp:430
This file collects some utility functions.
static unsigned int GetRealType(const tree_managerConstRef &TM, unsigned int index)
Return the real type.
virtual void DeclareFunctionTypes(const tree_nodeConstRef &tn)
Declares the types of the parameters of a function.
Definition: c_writer.cpp:333
dominance< BBGraph > * dominators
This class stores dominator information.
const HLS_managerConstRef HLSMgr
the hls manager
Definition: c_writer.hpp:95
virtual void WriteHeader()
Writes the header of the file.
Definition: c_writer.cpp:265
unsigned int create_new_identifier(std::map< unsigned int, std::string > &symbol_table)
create an identifier for the temporaries created by phi node destruction
Definition: c_writer.cpp:1641
std::map< unsigned int, std::string > basic_blocks_labels
Definition: c_writer.hpp:140
virtual void declare_cast_types(unsigned int funId, CustomSet< std::string > &locally_declared_types)
Declare all the types used in conversions.
Definition: c_writer.cpp:206
size_t bb_label_counter
Counter of the invocations of writeRoutineInstructions; this counter allows to print different labels...
Definition: c_writer.hpp:113
CustomOrderedSet< vertex > bb_analyzed
Definition: c_writer.hpp:139
static InstructionWriterRef CreateInstructionWriter(const ActorGraphBackend_Type actor_graph_backend_type, const application_managerConstRef AppM, const IndentedOutputStreamRef indented_output_stream, const ParameterConstRef parameters)
Factory method.
struct definition of the type node structures.
Definition: tree_node.hpp:1318
Class specification of the tree_reindex support class.
FunctionBehaviorConstRef local_rec_function_behavior
Definition: c_writer.hpp:143
const OpGraphConstRef CGetOpGraph(FunctionBehavior::graph_type gt) const
This method returns the operation graphs.
Class specification of the basic_block structure.
virtual void DeclareLocalVariables(const CustomSet< unsigned int > &to_be_declared, CustomSet< unsigned int > &already_declared_variables, CustomSet< std::string > &already_declared_types, const BehavioralHelperConstRef behavioral_helper, const var_pp_functorConstRef varFunc)
Declares the local variable; in case the variable used in the intialization of curVar hasn&#39;t been dec...
Definition: c_writer.cpp:1393
unsigned int size_t
Definition: test.c:1
unsigned int find_identifier_nodeID(const std::string &str) const
Return the nodeID of the identifier_node representing string str.
static std::string PrintType(const tree_managerConstRef &TM, const tree_nodeConstRef &type, bool global=false, bool print_qualifiers=false, bool print_storage=false, const tree_nodeConstRef &var=nullptr, const var_pp_functorConstRef &vppf=var_pp_functorConstRef(), const std::string &prefix="", const std::string &tail="")
Print a type and its variable in case var is not zero.
virtual void WriteFunctionBody(const unsigned int function_id)
Writes the body of a function.
Definition: c_writer.cpp:243
interface of a loop
const BBNodeInfoConstRef CGetBBNodeInfo(const vertex node) const
Return the info associated with a basic block.
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.
const BBGraphConstRef CGetBBGraph(FunctionBehavior::bb_graph_type gt=FunctionBehavior::BB) const
This method returns the basic block graphs.
const LoopsConstRef CGetLoops() const
Return the loops.
#define TYPE_WHILE
constant string identifying the node type of an WHILE operation.
Definition: op_graph.hpp:110
interface of loops finding algorithm
virtual void WriteBuiltinWaitCall()
Writes implementation of __builtin_wait_call.
Definition: c_writer.cpp:1922
Classes specification of the tree_node data structures not present in the gcc.
std::map< unsigned int, std::string > basic_block_prefix
string to be printed at the beginning of a given basic block
Definition: c_writer.hpp:130
this class is used to manage the command-line or XML options.
virtual void writeInclude(const std::string &file_name)
Writes an include directive.
Definition: c_writer.cpp:1383
std::vector< std::string > additionalIncludes
Definition: c_writer.hpp:190
virtual void WriteGlobalDeclarations()
Writes the global declarations.
Definition: c_writer.cpp:307
This file contains the routines necessary to create a C executable program.
unsigned int fake_max_tree_node_id
Definition: c_writer.hpp:127
virtual ~CWriter()
#define TYPE_ENTRY
constant identifying the node type of an entry node.
bool operator()(const std::pair< tree_nodeRef, tree_nodeRef > &x, const std::pair< tree_nodeRef, tree_nodeRef > &y) const
Compare position of two const tree nodes.
Definition: c_writer.cpp:123
Wrapper to call graph.
Control flow graph with feedback.
unsigned counter[N_THREADS]
Definition: data.c:3
#define DOALL_LOOP
parallelizable for loop
Definition: loop.hpp:132
x
Return the smallest n such that 2^n >= _x.
specialization of the instruction writer for the discrepancy analysis
std::map< vertex, std::map< unsigned int, std::string > > renaming_table
renaming table used by phi node destruction procedure
Definition: c_writer.hpp:136
refcount< var_pp_functor > var_pp_functorRef
virtual std::string print_type_declaration(unsigned int type) const
Print the declaration of a non built-in type.
const InstructionWriterRef getInstructionWriter() const
Returns the instruction writer.
Definition: c_writer.cpp:1378
BBGraphConstRef local_rec_bb_fcfgGraph
Definition: c_writer.hpp:147
static std::string GetTypeName(const tree_nodeConstRef &type)
Return name of the type.
#define CFG_SELECTOR
Control flow graph edge selector.
virtual void writeRoutineInstructions(const unsigned int function_index, const OpVertexSet &instructions, var_pp_functorConstRef variableFunctor, vertex bb_start=NULL_VERTEX, CustomOrderedSet< vertex > bb_end=CustomOrderedSet< vertex >())
Writes the instructions of the current routine, being it a task or a function of the original program...
Definition: c_writer.cpp:1150
static tree_nodeConstRef GetFunctionReturnType(const tree_nodeConstRef &function, bool void_as_null=true)
Return the return type of a function.
BehavioralHelperConstRef local_rec_behavioral_helper
Definition: c_writer.hpp:149
var_pp_functorConstRef local_rec_variableFunctor
Definition: c_writer.hpp:142
#define NULL_VERTEX
null vertex definition
Definition: graph.hpp:1305
Class specification of the manager of the tree structures extracted from the raw file.
virtual void WriteFunctionImplementation(unsigned int function_id)
Write function implementation.
Definition: c_writer.cpp:258
virtual void writePostInstructionInfo(const FunctionBehaviorConstRef, const vertex)
Write additional information on the given statement vertex, after the statements itself.
Definition: c_writer.cpp:426
A brief description of the C++ Header File.
CustomOrderedSet< vertex > local_rec_instructions
Definition: c_writer.hpp:144
static bool IsRealType(const tree_nodeConstRef &type)
Return true if the treenode is of real type.
virtual void writePreInstructionInfo(const FunctionBehaviorConstRef, const vertex)
Write additional information on the given statement vertex, before the statement itself.
Definition: c_writer.cpp:422
std::map< unsigned int, std::string > basic_block_tail
string to be printed at the end of a given basic block
Definition: c_writer.hpp:133
const InstructionWriterRef instrWriter
Contains the class used to write instructions.
Definition: c_writer.hpp:109
#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