58 unsigned int fun_id,
const DesignFlowManagerConstRef dfm)
68 auto p_type_head = ft->
prms;
69 if(p_type_head && GetPointer<const void_type>(
GET_CONST_NODE(p_type_head)))
73 " has void parameter type but has a parm_decl " +
81 const auto* p = GetPointerS<const tree_list>(
GET_CONST_NODE(p_type_head));
82 p_type_head = p->chan;
99 " has no parm_decl but in its function_type it takes a struct type " +
STR(p->valu));
110 switch(relationship_type)
114 relationships.insert(std::make_pair(BLOCK_FIX,
SAME_FUNCTION));
116 relationships.insert(std::make_pair(FIX_STRUCTS_PASSED_BY_VALUE, CALLING_FUNCTIONS));
117 relationships.insert(std::make_pair(REBUILD_INITIALIZATION, CALLING_FUNCTIONS));
133 return relationships;
138 bool changed =
false;
139 const auto TM =
AppM->get_tree_manager();
142 const auto fd = GetPointer<function_decl>(tn);
143 THROW_ASSERT(fd && fd->body,
"Node " +
STR(tn) +
"is not a function_decl or has no body");
146 const auto fname =
function_behavior->GetBehavioralHelper()->GetMangledFunctionName();
148 THROW_ASSERT(!ftype->varargs_flag,
"function " + fname +
" is varargs");
149 const auto HLSMgr = GetPointer<HLS_manager>(
AppM);
150 const auto func_arch = HLSMgr ? HLSMgr->module_arch->GetArchitecture(fname) :
nullptr;
155 THROW_ASSERT(tn->get_kind() != tree_reindex_K,
"function declaration " +
STR(tn) +
" is a tree_reindex");
156 unsigned int param_n = 0;
157 auto p_decl_it = fd->list_of_args.begin();
158 auto p_type_head = ftype->prms;
159 const auto has_param_types =
static_cast<bool>(p_type_head);
160 for(; p_decl_it != fd->list_of_args.cend(); p_decl_it++, param_n++)
162 const auto p_decl = *p_decl_it;
165 "-->Analyzing parameter " +
STR(p_decl) +
" with type " +
STR(p_type));
166 THROW_ASSERT(has_param_types == static_cast<bool>(p_type_head),
167 "function " + fname +
" has " +
STR(fd->list_of_args.size()) +
" parameters, but argument " +
168 STR(param_n) +
" (" +
STR(p_decl) +
169 ") has not a corresponding underlying type in function_type");
174 "function " + fname +
" has a struct parameter: " +
STR(p_decl) +
" with type " +
177 const auto pd = GetPointerS<const parm_decl>(
GET_CONST_NODE(p_decl));
179 const auto original_param_name =
180 pd->name ? GetPointerS<const identifier_node>(
GET_CONST_NODE(pd->name))->strg :
"";
183 if(ptd_type_size % 8)
191 const auto local_var_name =
"bambu_artificial_local_param_copy_" + original_param_name;
192 const auto local_var_identifier = tree_man->create_identifier_node(local_var_name);
193 const auto new_local_var_decl = tree_man->create_var_decl(
195 GetPointerS<const type_node>(
GET_CONST_NODE(p_type))->algn, pd->used,
202 "-->Substituting var_decl " +
STR(p_decl) +
" to parm_decl " +
STR(new_local_var_decl) +
203 " in all statements");
204 for(
const auto&
block :
sl->list_of_bloc)
207 for(
const auto& stmt :
block.second->CGetStmtList())
211 TM->ReplaceTreeNode(stmt, p_decl, new_local_var_decl);
218 "<--Substituted var_decl " +
STR(p_decl) +
" to parm_decl " +
STR(new_local_var_decl) +
219 " in all statements");
223 const auto ptr_type = tree_man->GetPointerType(p_type);
229 "-->Substituting type of parameter " +
STR(p_decl));
231 "---Changing type from " +
STR(p_type) +
" to " +
STR(
GET_NODE(ptr_type)));
232 GetPointerS<tree_list>(
GET_NODE(p_type_head))->valu = ptr_type;
234 "<--Substituted type of parameter " +
STR(p_decl));
240 const auto ptr_p_name =
"bambu_artificial_ptr_param_" + original_param_name;
241 const auto ptr_p_identifier = tree_man->create_identifier_node(ptr_p_name);
242 const auto ptr_p_decl = tree_man->create_parm_decl(ptr_p_identifier, ptr_type, pd->scpe, ptr_type,
246 const auto parm_it = func_arch->parms.find(original_param_name);
247 if(parm_it != func_arch->parms.end())
249 func_arch->parms[ptr_p_name] = parm_it->second;
250 func_arch->parms[ptr_p_name].at(FunctionArchitecture::parm_port) = ptr_p_name;
251 func_arch->parms.erase(parm_it);
258 "---Changing parm_decl from " +
STR(p_decl) +
" to " +
STR(
GET_NODE(ptr_p_decl)));
259 *p_decl_it = ptr_p_decl;
261 "<--Substituted parm_decl of " +
STR(p_decl) +
" with " +
STR(
GET_NODE(*p_decl_it)));
272 const auto entry_block =
sl->list_of_bloc.at(
BB_ENTRY);
273 const auto succ_blocks = entry_block->list_of_succ;
274 THROW_ASSERT(succ_blocks.size() == 1,
"entry basic block of function " + fname +
" has " +
275 STR(succ_blocks.size()) +
" successors");
276 bb_index = *(succ_blocks.begin());
278 "first basic block of function " + fname +
" not found");
280 "<--Selected first basic block of " + fname +
": " +
STR(bb_index));
282 const auto first_block =
sl->list_of_bloc.at(bb_index);
286 const auto memcpy_function = TM->GetFunction(
MEMCPY);
287 THROW_ASSERT(
AppM->get_tree_manager()->get_implementation_node(memcpy_function->index) != 0,
288 "inconsistent behavioral helper");
290 const std::vector<tree_nodeRef>
args = {
292 tree_man->CreateAddrExpr(
GET_NODE(new_local_var_decl), srcp),
296 TM->CreateUniqueIntegerCst(static_cast<long long>(ptd_type_size), formal_type_node)};
297 const auto gimple_call_memcpy = tree_man->create_gimple_call(memcpy_function, args,
function_id, srcp);
298 auto gn = GetPointer<gimple_node>(
GET_NODE(gimple_call_memcpy));
310 gn->artificial =
true;
312 "<--Created new call to memcpy: " +
STR(
GET_NODE(gimple_call_memcpy)));
314 first_block->PushFront(gimple_call_memcpy,
AppM);
320 p_type_head = GetPointer<const tree_list>(
GET_CONST_NODE(p_type_head))->chan;
324 "<--Analyzed parameter " +
STR(p_decl) +
" with type " +
STR(p_type));
330 for(
const auto&
block :
sl->list_of_bloc)
333 for(
const auto& stmt :
block.second->CGetStmtList())
337 const auto gn = GetPointer<const gimple_node>(
GET_CONST_NODE(stmt));
338 const auto srcp_default = gn->include_name +
":" +
STR(gn->line_number) +
":" +
STR(gn->column_number);
340 if(stmt_kind == gimple_assign_K or stmt_kind == gimple_call_K)
344 std::vector<tree_nodeRef>* arguments;
345 unsigned int call_tree_node_id = 0;
347 if(stmt_kind == gimple_assign_K)
349 const auto ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(stmt));
357 auto ce = GetPointer<call_expr>(
GET_NODE(ga->op1));
359 arguments = &ce->args;
360 call_tree_node_id = ce->index;
364 auto gc = GetPointer<gimple_call>(
GET_NODE(stmt));
366 arguments = &gc->args;
367 call_tree_node_id = gc->index;
374 if(called_node->
get_kind() == ssa_name_K)
376 const auto called_ssa_name =
STR(called_node);
378 "-->Indirect function call through ssa " + called_ssa_name);
381 const auto ft = GetPointer<const function_type>(
GET_CONST_NODE(f_ptr->ptd));
383 unsigned int param_n = 0;
384 auto p_type_head = ft->prms;
387 const auto*
const p = GetPointer<const tree_list>(
GET_CONST_NODE(p_type_head));
393 "function ssa " + called_ssa_name +
398 " calls function pointer " + called_ssa_name +
399 ": varargs function taking structs argument not supported");
401 const auto& actual_argument_node = arguments->at(param_n);
403 "---Actual argument " +
STR(actual_argument_node) +
" is " +
407 "op: " +
STR(stmt) +
" id: " +
STR(call_tree_node_id) +
" passes argument " +
408 STR(actual_argument_node) +
" to a call to function " + called_ssa_name +
409 " which has a struct/union parameter with type: " +
413 tree_man->CreateGimpleAssignAddrExpr(actual_argument_node,
function_id, srcp_default);
415 "---Changing parameter: creating pointer " +
STR(
GET_NODE(new_ga_node)));
416 block.second->PushBefore(new_ga_node, stmt,
AppM);
417 const auto new_ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(new_ga_node));
418 arguments->at(param_n) = new_ga->op0;
423 p_type_head = p->chan;
426 "<--Analyzed indirect call to ssa " + called_ssa_name);
432 "called_node = " +
STR(called_node) +
" is a " + called_node->
get_kind_text());
433 const auto ae = GetPointer<const addr_expr>(called_node);
434 const auto called_fu_decl_node =
GET_NODE(ae->op);
435 THROW_ASSERT(called_fu_decl_node->get_kind() == function_decl_K,
436 "node " +
STR(called_fu_decl_node) +
" is not function_decl but " +
437 called_fu_decl_node->get_kind_text());
438 const auto called_fd = GetPointer<const function_decl>(called_fu_decl_node);
440 const auto called_ftype =
451 "<--Function " + called_fname +
" is varargs but has no body");
459 auto p_type_head = called_ftype->prms;
460 const auto has_param_types =
static_cast<bool>(p_type_head);
461 unsigned int param_n = 0;
462 auto p_decl_it = called_fd->list_of_args.begin();
463 for(; p_decl_it != called_fd->list_of_args.cend(); p_decl_it++, param_n++)
465 const auto& p_decl = *p_decl_it;
468 "-->Analyzing parameter " +
STR(p_decl) +
" with type " +
STR(p_type));
470 THROW_ASSERT(static_cast<bool>(has_param_types) == static_cast<bool>(p_type_head),
471 "function " + called_fname +
" has " +
STR(called_fd->list_of_args.size()) +
472 " parameters, but argument " +
STR(param_n) +
" (" +
STR(p_decl) +
473 ") has not a corresponding underlying type in function_type");
476 p_type_head = GetPointer<const tree_list>(
GET_CONST_NODE(p_type_head))->chan;
482 "function " + called_fname +
" has a struct parameter: " +
STR(p_decl) +
483 " with type " +
STR(p_type));
484 if(called_ftype->varargs_flag)
486 THROW_ERROR(
"op: " +
STR(stmt) +
" id: " +
STR(call_tree_node_id) +
" calls function " +
487 called_fname +
": varargs function taking structs argument not supported");
489 const auto& actual_argument_node = arguments->at(param_n);
491 "---Actual argument " +
STR(actual_argument_node) +
" is " +
495 "op: " +
STR(stmt) +
" id: " +
STR(call_tree_node_id) +
" passes argument " +
496 STR(actual_argument_node) +
" to a call to function " + called_fname +
497 " which has a struct/union parameter: " +
STR(p_decl) +
" but " +
498 STR(actual_argument_node) +
" is a " +
500 const auto new_ga_node =
501 tree_man->CreateGimpleAssignAddrExpr(actual_argument_node,
function_id, srcp_default);
503 "---Changing parameter: creating pointer " +
STR(
GET_NODE(new_ga_node)));
504 block.second->PushBefore(new_ga_node, stmt,
AppM);
505 const auto* new_ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(new_ga_node));
506 arguments->at(param_n) = new_ga->op0;
510 "<--Analyzed parameter " +
STR(p_decl) +
" with type " +
STR(p_type));
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
static tree_nodeConstRef GetFormalIth(const tree_nodeConstRef &obj, unsigned int parm_index)
Return the type of the ith formal parameter in case index_obj is a call_expr.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
static bool IsUnionType(const tree_nodeConstRef &type)
Return if treenode is an union.
~FixStructsPassedByValue() override
Destructor.
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;.
#define MEMCPY
constant string identifying the operation performed when two objects are memcopied.
File containing functions and utilities to support the printing of debug messagges.
Step successfully executed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
#define BB_EXIT
constant identifying the basic block node of type exit
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
struct definition of the source position.
RelationshipType
The relationship type.
struct definition of the function_decl tree node.
Source must be executed to satisfy target.
static std::string GetString(const enum kind k)
Given a kind, return the corresponding string.
tree_nodeRef prms
prms field is a list of types of arguments expected, this list is made of tree_list nodes...
FixStructsPassedByValue(const ParameterConstRef params, const application_managerRef AM, unsigned int fun_id, const DesignFlowManagerConstRef dfm)
Constructor.
struct definition of the function_type tree node.
Data structure describing a basic block at tree level.
std::string include_name
include_name is a filename string, this can be the location of a reference, if no definition has been...
static std::string GetMangledFunctionName(const function_decl *fd)
Return the mangled function name.
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
virtual std::string get_kind_text() const =0
Virtual function returning the name of the actual class.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
Target must be reexecuted.
#define BB_ENTRY
constant identifying the basic block node of type entry
#define GET_CONST_NODE(t)
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
This struct specifies the block node.
This file collects some utility functions.
std::vector< tree_nodeRef > list_of_args
args field holds a chain of parm_decl nodes for the arguments.
const unsigned int function_id
The index of the function to be analyzed.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
DesignFlowStep_Status InternalExec() override
Execute the step.
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
static bool IsStructType(const tree_nodeConstRef &type)
Return true if treenode is a record.
const CustomUnorderedSet< std::pair< FrontendFlowStepType, FunctionRelationship > > ComputeFrontendRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
this class is used to manage the command-line or XML options.
static bool cannot_have_struct_parameters(const function_decl *const fd, const function_type *const ft)
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
int debug_level
The debug level.
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...