From 2c4deee0c3d3f3c63ef0e9816ca9f39fdad45af8 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 29 Jan 2016 16:34:10 +0100 Subject: [PATCH] vhdlpp: Support for subprogram overloading. --- vhdlpp/architec_elaborate.cc | 9 ++- vhdlpp/architec_emit.cc | 15 +++- vhdlpp/debug.cc | 39 ++++++---- vhdlpp/expression_elaborate.cc | 49 +++++++----- vhdlpp/library.cc | 8 +- vhdlpp/library.h | 11 ++- vhdlpp/package.cc | 44 +++++++---- vhdlpp/package_emit.cc | 25 +++++-- vhdlpp/parse.y | 9 +-- vhdlpp/scope.cc | 131 +++++++++++++++++++++++++++------ vhdlpp/scope.h | 20 +++-- vhdlpp/sequential_elaborate.cc | 16 +++- vhdlpp/std_funcs.cc | 23 +++--- vhdlpp/std_funcs.h | 2 +- vhdlpp/subprogram.h | 2 +- 15 files changed, 288 insertions(+), 115 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 806519c51..e35209f33 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -61,9 +61,14 @@ int Architecture::elaborate(Entity*entity) } // Elaborate subprograms - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { - errors += cur->second->elaborate(); + const SubHeaderList& subp_list = cur->second; + + for(SubHeaderList::const_iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + errors += (*it)->elaborate(); + } } // Create 'initial' and 'final' blocks for implicit // initalization and clean-up actions diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index 42e5e2c5c..8fd0ee569 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -103,11 +103,18 @@ int Architecture::emit(ostream&out, Entity*entity) errors += emit_signals(out, entity, this); errors += emit_variables(out, entity, this); - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++ cur) { - // Do not emit unbounded functions, we will just need fixed instances later - if(!cur->second->unbounded()) - errors += cur->second->emit_package(out); + const SubHeaderList& subp_list = cur->second; + + for(SubHeaderList::const_iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + SubprogramHeader*subp = *it; + + // Do not emit unbounded functions, we will just need fixed instances later + if(!subp->unbounded()) + errors += subp->emit_package(out); + } } for (list::iterator cur = statements_.begin() diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 6f044b2e8..3669fd489 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -150,22 +150,35 @@ void ScopeBase::dump_scope(ostream&out) const } // Dump subprograms out << " -- Imported Subprograms" << endl; - for (map::const_iterator cur = use_subprograms_.begin() - ; cur != use_subprograms_.end() ; ++cur) { - out << " subprogram " << cur->first << " is" << endl; - cur->second->dump(out); - if(cur->second->body()) - cur->second->body()->dump(out); - out << " end subprogram " << cur->first << endl; + for (map::const_iterator cur = use_subprograms_.begin() + ; cur != cur_subprograms_.end() ; ++ cur) { + const SubHeaderList& subp_list = cur->second; + + for(SubHeaderList::const_iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + const SubprogramHeader*subp = *it; + out << " subprogram " << cur->first << " is" << endl; + subp->dump(out); + if(subp->body()) + subp->body()->dump(out); + out << " end subprogram " << cur->first << endl; + } } + out << " -- Subprograms from this scope" << endl; - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { - out << " subprogram " << cur->first << " is" << endl; - cur->second->dump(out); - if(cur->second->body()) - cur->second->body()->dump(out); - out << " end subprogram " << cur->first << endl; + const SubHeaderList& subp_list = cur->second; + + for(SubHeaderList::const_iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + const SubprogramHeader*subp = *it; + out << " subprogram " << cur->first << " is" << endl; + subp->dump(out); + if(subp->body()) + subp->body()->dump(out); + out << " end subprogram " << cur->first << endl; + } } // Dump component declarations out << " -- Components" << endl; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 76850aafd..c95a26077 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -783,22 +783,29 @@ int ExpConditional::case_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VT return errors; } -const VType*ExpFunc::probe_type(Entity*, ScopeBase*scope) const +const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const { SubprogramHeader*prog = def_; if(!prog) { - prog = scope->find_subprogram(name_); - } + list arg_types; - if(!prog) - prog = library_find_subprogram(name_); + for(vector::const_iterator it = argv_.begin(); + it != argv_.end(); ++it) { + arg_types.push_back((*it)->probe_type(ent, scope)); + } - if(!prog) { - cerr << get_fileline() << ": sorry: could not find function "; - emit_subprogram_sig(cerr, name_, arg_types); - cerr << endl; - ivl_assert(*this, false); + prog = scope->match_subprogram(name_, &arg_types); + + if(!prog) + prog = library_match_subprogram(name_, &arg_types); + + if(!prog) { + cerr << get_fileline() << ": sorry: could not find function "; + emit_subprogram_sig(cerr, name_, arg_types); + cerr << endl; + ivl_assert(*this, false); + } } return prog->peek_return_type(); @@ -808,13 +815,19 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) { int errors = 0; - ivl_assert(*this, scope); - SubprogramHeader*prog = scope->find_subprogram(name_); + ivl_assert(*this, def_ == 0); // do not elaborate twice - if(!prog) - prog = library_find_subprogram(name_); + // Create a list of argument types to find a matching subprogram + list arg_types; + for(vector::iterator it = argv_.begin(); + it != argv_.end(); ++it) + arg_types.push_back((*it)->probe_type(ent, scope)); + + def_ = scope->match_subprogram(name_, &arg_types); + + if(!def_) + def_ = library_match_subprogram(name_, &arg_types); - def_ = prog; if(!def_) { cerr << get_fileline() << ": error: could not find function "; emit_subprogram_sig(cerr, name_, arg_types); @@ -824,15 +837,15 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) // Elaborate arguments for (size_t idx = 0; idx < argv_.size(); ++idx) { - errors += prog->elaborate_argument(argv_[idx], idx, ent, scope); + errors += def_->elaborate_argument(argv_[idx], idx, ent, scope); } // SystemVerilog functions work only with defined size data types, therefore // if header does not specify argument or return type size, create a function // instance that work with this particular size. if(def_ && !def_->is_std() && def_->unbounded()) { - def_ = prog->make_instance(argv_, scope); - name_ = def_->name(); + def_ = def_->make_instance(argv_, scope); + name_ = def_->name(); // TODO necessary? } return errors; diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index beb0838d3..fb015feab 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -1,6 +1,8 @@ /* * Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) + * Copyright CERN 2016 + * @author Maciej Suminski * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -73,9 +75,9 @@ void library_add_directory(const char*directory) library_search_path.push_front(directory); } -SubprogramHeader*library_find_subprogram(perm_string name) +SubprogramHeader*library_match_subprogram(perm_string name, const list*params) { - SubprogramHeader*subp = NULL; + SubprogramHeader*subp; map::const_iterator lib_it; for(lib_it = libraries.begin(); lib_it != libraries.end(); ++lib_it) { @@ -83,7 +85,7 @@ SubprogramHeader*library_find_subprogram(perm_string name) map::const_iterator pack_it; for(pack_it = lib.packages.begin(); pack_it != lib.packages.end(); ++pack_it) { - if((subp = pack_it->second->find_subprogram(name))) + if((subp = pack_it->second->match_subprogram(name, params))) return subp; } } diff --git a/vhdlpp/library.h b/vhdlpp/library.h index 7fb95851e..5596db870 100644 --- a/vhdlpp/library.h +++ b/vhdlpp/library.h @@ -19,15 +19,18 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -class SubprogramHeader; +#include -extern void library_set_work_path(const char*work_path); -extern void library_add_directory(const char*directory); +class SubprogramHeader; +class VType; + +void library_set_work_path(const char*work_path); +void library_add_directory(const char*directory); int elaborate_libraries(void); int emit_packages(void); -extern SubprogramHeader*library_find_subprogram(perm_string name); +SubprogramHeader*library_match_subprogram(perm_string name, const list*params); #endif /* IVL_library_H */ diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index 63215fee3..d58f82093 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -24,6 +24,8 @@ # include "parse_misc.h" # include "std_types.h" # include "ivl_assert.h" +# include +# include Package::Package(perm_string n, const ActiveScope&ref) : Scope(ref), name_(n) @@ -45,9 +47,14 @@ int Package::elaborate() { int errors = 0; - for (map::const_iterator cur = cur_subprograms_.begin() - ; cur != cur_subprograms_.end() ; ++cur) { - errors += cur->second->elaborate(); + for (map::iterator cur = cur_subprograms_.begin() + ; cur != cur_subprograms_.end() ; ++ cur) { + SubHeaderList& subp_list = cur->second; + + for(SubHeaderList::iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + errors += (*it)->elaborate(); + } } return errors; @@ -108,10 +115,15 @@ void Package::write_to_stream(ostream&fd) const fd << ";" << endl; } - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { - cur->second->write_to_stream(fd); - fd << ";" << endl; + const SubHeaderList& subp_list = cur->second; + + for(SubHeaderList::const_iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + (*it)->write_to_stream(fd); + fd << ";" << endl; + } } for (map::const_iterator cur = old_components_.begin() @@ -128,14 +140,20 @@ void Package::write_to_stream(ostream&fd) const fd << "end package " << name_ << ";" << endl; fd << "package body " << name_ << " is" << endl; - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { - SubprogramHeader*subp = cur->second; - if(subp->body()) { - subp->write_to_stream(fd); - fd << " is" << endl; - subp->body()->write_to_stream(fd); + const SubHeaderList& subp_list = cur->second; + + for(SubHeaderList::const_iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + const SubprogramHeader*subp = *it; + + if(subp->body()) { + subp->write_to_stream(fd); + fd << " is" << endl; + subp->body()->write_to_stream(fd); + } } - } + } fd << "end " << name_ << ";" << endl; } diff --git a/vhdlpp/package_emit.cc b/vhdlpp/package_emit.cc index 77d314231..962f68a65 100644 --- a/vhdlpp/package_emit.cc +++ b/vhdlpp/package_emit.cc @@ -20,8 +20,9 @@ # include "package.h" # include "subprogram.h" -# include # include "ivl_assert.h" +# include +# include using namespace std; @@ -64,14 +65,22 @@ int Package::emit_package(ostream&fd) const //} fd << "package \\" << name() << " ;" << endl; - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++ cur) { - // Do not emit unbounded functions, we will just need fixed instances later - if(!cur->second->unbounded()) - errors += cur->second->emit_package(fd); - else - fd << "/* function " << cur->second->name() << - " has to be instantiated, skipping */" << endl; + const SubHeaderList& subp_list = cur->second; + + for(SubHeaderList::const_iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + SubprogramHeader*header = *it; + + // Do not emit unbounded functions, we will just need fixed instances later + if(!header->unbounded()) + errors += header->emit_package(fd); + else + fd << "/* function " << header->name() + << " has to be instantiated, skipping */" << endl; + } + } fd << "endpackage /* " << name() << " */" << endl; diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 95853a03a..0d7b706a9 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -1701,7 +1701,8 @@ name /* IEEE 1076-2008 P8.1 */ tmp = parse_char_enums($1); if(!tmp) { perm_string name = lex_strings.make($1); - if(active_scope->find_subprogram(name) && !parse_type_by_name(name)) + /* There are functions that have the same name types, e.g. integer */ + if(!active_scope->find_subprogram(name).empty() && !parse_type_by_name(name)) tmp = new ExpFunc(name); else tmp = new ExpName(name); @@ -2565,12 +2566,10 @@ subprogram_body /* IEEE 1076-2008 P4.3 */ K_begin subprogram_statement_part K_end subprogram_kind_opt identifier_opt ';' { SubprogramHeader*prog = $1; - SubprogramHeader*tmp = active_scope->recall_subprogram(prog->name()); - if (tmp && prog->compare_specification(tmp)) { + SubprogramHeader*tmp = active_scope->recall_subprogram(prog); + if (tmp) { delete prog; prog = tmp; - } else if (tmp) { - errormsg(@1, "Subprogram specification for %s doesn't match specification in package header.\n", prog->name().str()); } SubprogramBody*body = new SubprogramBody(); diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 5084986a3..395804962 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -70,9 +70,14 @@ ScopeBase::ScopeBase(const ActiveScope&ref) // an active scope and is making the actual scope. At this point // we know that "this" is the parent scope for the subprograms, // so set it now. - for (map::iterator cur = cur_subprograms_.begin() - ; cur != cur_subprograms_.end(); ++cur) { - cur->second->set_parent(this); + for (map::iterator cur = cur_subprograms_.begin() + ; cur != cur_subprograms_.end(); ++cur) { + SubHeaderList& subp_list = cur->second; + + for (SubHeaderList::iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + (*it)->set_parent(this); + } } } @@ -94,7 +99,10 @@ void ScopeBase::cleanup() delete_all(new_components_); delete_all(cur_types_); delete_all(cur_constants_); - delete_all(cur_subprograms_); + for (map::iterator cur = cur_subprograms_.begin() + ; cur != cur_subprograms_.end() ; ++cur) { + delete_all(cur->second); + } } const VType*ScopeBase::find_type(perm_string by_name) @@ -157,32 +165,42 @@ const InterfacePort* ScopeBase::find_param(perm_string) const const InterfacePort* ScopeBase::find_param_all(perm_string by_name) const { - for(map::const_iterator it = use_subprograms_.begin(); - it != use_subprograms_.end(); ++it) { - if(const InterfacePort*port = it->second->find_param(by_name)) - return port; + for(map::const_iterator cur = use_subprograms_.begin(); + cur != use_subprograms_.end(); ++cur) { + const SubHeaderList& subp_list = cur->second; + + for(SubHeaderList::const_iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + if(const InterfacePort*port = (*it)->find_param(by_name)) + return port; + } } - for(map::const_iterator it = cur_subprograms_.begin(); - it != cur_subprograms_.end(); ++it) { - if(const InterfacePort*port = it->second->find_param(by_name)) - return port; + for(map::const_iterator cur = cur_subprograms_.begin(); + cur != cur_subprograms_.end(); ++cur) { + const SubHeaderList& subp_list = cur->second; + + for(SubHeaderList::const_iterator it = subp_list.begin(); + it != subp_list.end(); ++it) { + if(const InterfacePort*port = (*it)->find_param(by_name)) + return port; + } } return NULL; } -SubprogramHeader* ScopeBase::find_subprogram(perm_string name) const +SubHeaderList ScopeBase::find_subprogram(perm_string name) const { - map::const_iterator cur; + map::const_iterator cur; cur = cur_subprograms_.find(name); if (cur != cur_subprograms_.end()) - return cur->second; + return cur->second; cur = use_subprograms_.find(name); if (cur != use_subprograms_.end()) - return cur->second; + return cur->second; return find_std_subprogram(name); } @@ -217,9 +235,9 @@ void ScopeBase::do_use_from(const ScopeBase*that) old_components_[cur->first] = cur->second; } - for (map::const_iterator cur = that->cur_subprograms_.begin() + for (map::const_iterator cur = that->cur_subprograms_.begin() ; cur != that->cur_subprograms_.end() ; ++ cur) { - if (cur->second == 0) + if (cur->second.empty()) continue; use_subprograms_[cur->first] = cur->second; } @@ -266,21 +284,86 @@ void ScopeBase::transfer_from(ScopeBase&ref, transfer_type_t what) } } +SubprogramHeader*ScopeBase::match_subprogram(perm_string name, + const list*params) const +{ + int req_param_count = params ? params->size() : 0; + + // Find all subprograms with matching name + SubHeaderList l = find_std_subprogram(name); + map::const_iterator cur; + + cur = use_subprograms_.find(name); + if (cur != use_subprograms_.end()) + copy(cur->second.begin(), cur->second.end(), + front_insert_iterator(l)); + + cur = cur_subprograms_.find(name); + if(cur != cur_subprograms_.end()) + copy(cur->second.begin(), cur->second.end(), + front_insert_iterator(l)); + + // Find the matching one + for(SubHeaderList::iterator it = l.begin(); it != l.end(); ++it) { + SubprogramHeader*subp = *it; + + if(req_param_count != subp->param_count()) + continue; + + // Do not check the return type here, it might depend on the arguments + + if(params) { + list::const_iterator p = params->begin(); + bool ok = true; + + for(int i = 0; i < req_param_count; ++i) { + const VType*param_type = subp->peek_param_type(i); + + if(*p && param_type && !param_type->type_match(*p)) { + ok = false; + break; + } + + ++p; + } + + if(!ok) + continue; // check another function + } + + // Yay, we have a match! + return subp; + } + + return NULL; +} + void ActiveScope::set_package_header(Package*pkg) { assert(package_header_ == 0); package_header_ = pkg; } -SubprogramHeader* ActiveScope::recall_subprogram(perm_string name) const +SubprogramHeader* ActiveScope::recall_subprogram(const SubprogramHeader*subp) const { - if (SubprogramHeader*tmp = find_subprogram(name)) - return tmp; + list arg_types; + SubprogramHeader*tmp; - if (package_header_) - return package_header_->find_subprogram(name); + for(int i = 0; i < subp->param_count(); ++i) + arg_types.push_back(subp->peek_param_type(i)); - return 0; + if ((tmp = match_subprogram(subp->name(), &arg_types))) { + assert(!tmp->body()); + return tmp; + } + + if (package_header_) { + tmp = package_header_->match_subprogram(subp->name(), &arg_types); + assert(!tmp || !tmp->body()); + return tmp; + } + + return NULL; } bool ActiveScope::is_vector_name(perm_string name) const diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index a95d1e4cd..3563692d9 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -36,6 +36,8 @@ class SubprogramHeader; class VType; class SequentialStmt; +typedef list SubHeaderList; + template struct delete_object{ void operator()(T* item) { delete item; } @@ -59,7 +61,7 @@ class ScopeBase { Variable* find_variable(perm_string by_name) const; virtual const InterfacePort* find_param(perm_string by_name) const; const InterfacePort* find_param_all(perm_string by_name) const; - SubprogramHeader* find_subprogram(perm_string by_name) const; + SubHeaderList find_subprogram(perm_string by_name) const; // Checks if a string is one of possible enum values. If so, the enum // type is returned, otherwise NULL. const VTypeEnum* is_enum_name(perm_string name) const; @@ -70,10 +72,10 @@ class ScopeBase { void transfer_from(ScopeBase&ref, transfer_type_t what = ALL); inline void bind_subprogram(perm_string name, SubprogramHeader*obj) - { map::iterator it; + { map::iterator it; if((it = use_subprograms_.find(name)) != use_subprograms_.end() ) - use_subprograms_.erase(it); - cur_subprograms_[name] = obj; + it->second.remove(obj); + cur_subprograms_[name].push_back(obj); } // Adds a statement to implicit initializers list @@ -92,6 +94,10 @@ class ScopeBase { void dump_scope(ostream&out) const; + // Looks for a subprogram with specified name and parameter types. + SubprogramHeader*match_subprogram(perm_string name, + const list*params) const; + protected: void cleanup(); @@ -134,8 +140,8 @@ class ScopeBase { std::map use_constants_; //imported constants std::map cur_constants_; //current constants - std::map use_subprograms_; //imported - std::map cur_subprograms_; //current + std::map use_subprograms_; //imported + std::map cur_subprograms_; //current std::list use_enums_; @@ -191,7 +197,7 @@ class ActiveScope : public ScopeBase { // Locate the subprogram by name. The subprogram body uses // this to locate the subprogram declaration. Note that the // subprogram may be in a package header. - SubprogramHeader* recall_subprogram(perm_string name) const; + SubprogramHeader* recall_subprogram(const SubprogramHeader*subp) const; /* All bind_name function check if the given name was present * in previous scopes. If it is found, it is erased (but the pointer diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 4d67daa65..93d185bfd 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -178,10 +178,22 @@ int ProcedureCall::elaborate(Entity*ent, ScopeBase*scope) { int errors = 0; - def_ = scope->find_subprogram(name_); + assert(!def_); // do not elaborate twice + + // Create a list of argument types to find a matching subprogram + list arg_types; + if(param_list_) { + for(list::iterator it = param_list_->begin(); + it != param_list_->end(); ++it) { + named_expr_t* e = *it; + arg_types.push_back(e->expr()->probe_type(ent, scope)); + } + } + + def_ = scope->match_subprogram(name_, &arg_types); if(!def_) - def_ = library_find_subprogram(name_); + def_ = library_match_subprogram(name_, &arg_types); if(!def_) { cerr << get_fileline() << ": error: could not find procedure "; diff --git a/vhdlpp/std_funcs.cc b/vhdlpp/std_funcs.cc index 50d6c1803..f3a4fb441 100644 --- a/vhdlpp/std_funcs.cc +++ b/vhdlpp/std_funcs.cc @@ -22,11 +22,11 @@ #include "std_types.h" #include "scope.h" -static std::map std_subprograms; +static std::map std_subprograms; static inline void register_std_subprogram(SubprogramHeader*header) { - std_subprograms[header->name()] = header; + std_subprograms[header->name()].push_back(header); } // Special case: to_integer function @@ -356,17 +356,20 @@ void preload_std_funcs(void) void delete_std_funcs() { - for(std::map::iterator it = std_subprograms.begin(); - it != std_subprograms.end(); ++it) { - delete it->second; + for(std::map::iterator cur = std_subprograms.begin(); + cur != std_subprograms.end(); ++cur) { + for(SubHeaderList::const_iterator it = cur->second.begin(); + it != cur->second.end(); ++it) { + delete *it; + } } } -SubprogramHeader*find_std_subprogram(perm_string name) +SubHeaderList find_std_subprogram(perm_string name) { - map::const_iterator cur = std_subprograms.find(name); - if (cur != std_subprograms.end()) - return cur->second; + map::const_iterator cur = std_subprograms.find(name); + if(cur != std_subprograms.end()) + return cur->second; - return NULL; + return SubHeaderList(); } diff --git a/vhdlpp/std_funcs.h b/vhdlpp/std_funcs.h index 0f5645aa3..f3a904d44 100644 --- a/vhdlpp/std_funcs.h +++ b/vhdlpp/std_funcs.h @@ -29,6 +29,6 @@ void preload_std_funcs(); void delete_std_funcs(); // Returns subprogram header for a requested function or NULL if it does not exist. -SubprogramHeader*find_std_subprogram(perm_string name); +SubHeaderList find_std_subprogram(perm_string name); #endif /* IVL_std_funcs_H */ diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index 6eb0446c9..0338dc002 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -32,7 +32,6 @@ class InterfacePort; class SequentialStmt; class VType; -class SubprogramHeader; class SubprogramBody : public LineInfo, public ScopeBase { @@ -73,6 +72,7 @@ class SubprogramHeader : public LineInfo { // matches this subprogram and that subprogram. bool compare_specification(SubprogramHeader*that) const; + int param_count() const { return ports_ ? ports_->size() : 0; } const InterfacePort*find_param(perm_string nam) const; const InterfacePort*peek_param(int idx) const; const VType*peek_param_type(int idx) const;