vhdlpp: Support for subprogram overloading.
This commit is contained in:
parent
cfa038e75c
commit
2c4deee0c3
|
|
@ -61,9 +61,14 @@ int Architecture::elaborate(Entity*entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Elaborate subprograms
|
// Elaborate subprograms
|
||||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
for (map<perm_string,SubHeaderList>::const_iterator cur = cur_subprograms_.begin()
|
||||||
; cur != cur_subprograms_.end() ; ++cur) {
|
; 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
|
// Create 'initial' and 'final' blocks for implicit
|
||||||
// initalization and clean-up actions
|
// initalization and clean-up actions
|
||||||
|
|
|
||||||
|
|
@ -103,11 +103,18 @@ int Architecture::emit(ostream&out, Entity*entity)
|
||||||
errors += emit_signals(out, entity, this);
|
errors += emit_signals(out, entity, this);
|
||||||
errors += emit_variables(out, entity, this);
|
errors += emit_variables(out, entity, this);
|
||||||
|
|
||||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
for (map<perm_string,SubHeaderList>::const_iterator cur = cur_subprograms_.begin()
|
||||||
; cur != cur_subprograms_.end() ; ++ cur) {
|
; cur != cur_subprograms_.end() ; ++ cur) {
|
||||||
// Do not emit unbounded functions, we will just need fixed instances later
|
const SubHeaderList& subp_list = cur->second;
|
||||||
if(!cur->second->unbounded())
|
|
||||||
errors += cur->second->emit_package(out);
|
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<Architecture::Statement*>::iterator cur = statements_.begin()
|
for (list<Architecture::Statement*>::iterator cur = statements_.begin()
|
||||||
|
|
|
||||||
|
|
@ -150,22 +150,35 @@ void ScopeBase::dump_scope(ostream&out) const
|
||||||
}
|
}
|
||||||
// Dump subprograms
|
// Dump subprograms
|
||||||
out << " -- Imported Subprograms" << endl;
|
out << " -- Imported Subprograms" << endl;
|
||||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = use_subprograms_.begin()
|
for (map<perm_string,SubHeaderList>::const_iterator cur = use_subprograms_.begin()
|
||||||
; cur != use_subprograms_.end() ; ++cur) {
|
; cur != cur_subprograms_.end() ; ++ cur) {
|
||||||
out << " subprogram " << cur->first << " is" << endl;
|
const SubHeaderList& subp_list = cur->second;
|
||||||
cur->second->dump(out);
|
|
||||||
if(cur->second->body())
|
for(SubHeaderList::const_iterator it = subp_list.begin();
|
||||||
cur->second->body()->dump(out);
|
it != subp_list.end(); ++it) {
|
||||||
out << " end subprogram " << cur->first << endl;
|
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;
|
out << " -- Subprograms from this scope" << endl;
|
||||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
for (map<perm_string,SubHeaderList>::const_iterator cur = cur_subprograms_.begin()
|
||||||
; cur != cur_subprograms_.end() ; ++cur) {
|
; cur != cur_subprograms_.end() ; ++cur) {
|
||||||
out << " subprogram " << cur->first << " is" << endl;
|
const SubHeaderList& subp_list = cur->second;
|
||||||
cur->second->dump(out);
|
|
||||||
if(cur->second->body())
|
for(SubHeaderList::const_iterator it = subp_list.begin();
|
||||||
cur->second->body()->dump(out);
|
it != subp_list.end(); ++it) {
|
||||||
out << " end subprogram " << cur->first << endl;
|
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
|
// Dump component declarations
|
||||||
out << " -- Components" << endl;
|
out << " -- Components" << endl;
|
||||||
|
|
|
||||||
|
|
@ -783,22 +783,29 @@ int ExpConditional::case_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VT
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VType*ExpFunc::probe_type(Entity*, ScopeBase*scope) const
|
const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const
|
||||||
{
|
{
|
||||||
SubprogramHeader*prog = def_;
|
SubprogramHeader*prog = def_;
|
||||||
|
|
||||||
if(!prog) {
|
if(!prog) {
|
||||||
prog = scope->find_subprogram(name_);
|
list<const VType*> arg_types;
|
||||||
}
|
|
||||||
|
|
||||||
if(!prog)
|
for(vector<Expression*>::const_iterator it = argv_.begin();
|
||||||
prog = library_find_subprogram(name_);
|
it != argv_.end(); ++it) {
|
||||||
|
arg_types.push_back((*it)->probe_type(ent, scope));
|
||||||
|
}
|
||||||
|
|
||||||
if(!prog) {
|
prog = scope->match_subprogram(name_, &arg_types);
|
||||||
cerr << get_fileline() << ": sorry: could not find function ";
|
|
||||||
emit_subprogram_sig(cerr, name_, arg_types);
|
if(!prog)
|
||||||
cerr << endl;
|
prog = library_match_subprogram(name_, &arg_types);
|
||||||
ivl_assert(*this, false);
|
|
||||||
|
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();
|
return prog->peek_return_type();
|
||||||
|
|
@ -808,13 +815,19 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
||||||
ivl_assert(*this, scope);
|
ivl_assert(*this, def_ == 0); // do not elaborate twice
|
||||||
SubprogramHeader*prog = scope->find_subprogram(name_);
|
|
||||||
|
|
||||||
if(!prog)
|
// Create a list of argument types to find a matching subprogram
|
||||||
prog = library_find_subprogram(name_);
|
list<const VType*> arg_types;
|
||||||
|
for(vector<Expression*>::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_) {
|
if(!def_) {
|
||||||
cerr << get_fileline() << ": error: could not find function ";
|
cerr << get_fileline() << ": error: could not find function ";
|
||||||
emit_subprogram_sig(cerr, name_, arg_types);
|
emit_subprogram_sig(cerr, name_, arg_types);
|
||||||
|
|
@ -824,15 +837,15 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
|
||||||
|
|
||||||
// Elaborate arguments
|
// Elaborate arguments
|
||||||
for (size_t idx = 0; idx < argv_.size(); ++idx) {
|
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
|
// SystemVerilog functions work only with defined size data types, therefore
|
||||||
// if header does not specify argument or return type size, create a function
|
// if header does not specify argument or return type size, create a function
|
||||||
// instance that work with this particular size.
|
// instance that work with this particular size.
|
||||||
if(def_ && !def_->is_std() && def_->unbounded()) {
|
if(def_ && !def_->is_std() && def_->unbounded()) {
|
||||||
def_ = prog->make_instance(argv_, scope);
|
def_ = def_->make_instance(argv_, scope);
|
||||||
name_ = def_->name();
|
name_ = def_->name(); // TODO necessary?
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||||
|
* Copyright CERN 2016
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* 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);
|
library_search_path.push_front(directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
SubprogramHeader*library_find_subprogram(perm_string name)
|
SubprogramHeader*library_match_subprogram(perm_string name, const list<const VType*>*params)
|
||||||
{
|
{
|
||||||
SubprogramHeader*subp = NULL;
|
SubprogramHeader*subp;
|
||||||
map<perm_string,struct library_contents>::const_iterator lib_it;
|
map<perm_string,struct library_contents>::const_iterator lib_it;
|
||||||
|
|
||||||
for(lib_it = libraries.begin(); lib_it != libraries.end(); ++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<perm_string,Package*>::const_iterator pack_it;
|
map<perm_string,Package*>::const_iterator pack_it;
|
||||||
|
|
||||||
for(pack_it = lib.packages.begin(); pack_it != lib.packages.end(); ++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;
|
return subp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,18 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class SubprogramHeader;
|
#include <list>
|
||||||
|
|
||||||
extern void library_set_work_path(const char*work_path);
|
class SubprogramHeader;
|
||||||
extern void library_add_directory(const char*directory);
|
class VType;
|
||||||
|
|
||||||
|
void library_set_work_path(const char*work_path);
|
||||||
|
void library_add_directory(const char*directory);
|
||||||
|
|
||||||
int elaborate_libraries(void);
|
int elaborate_libraries(void);
|
||||||
int emit_packages(void);
|
int emit_packages(void);
|
||||||
|
|
||||||
extern SubprogramHeader*library_find_subprogram(perm_string name);
|
SubprogramHeader*library_match_subprogram(perm_string name, const list<const VType*>*params);
|
||||||
|
|
||||||
#endif /* IVL_library_H */
|
#endif /* IVL_library_H */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@
|
||||||
# include "parse_misc.h"
|
# include "parse_misc.h"
|
||||||
# include "std_types.h"
|
# include "std_types.h"
|
||||||
# include "ivl_assert.h"
|
# include "ivl_assert.h"
|
||||||
|
# include <list>
|
||||||
|
# include <iterator>
|
||||||
|
|
||||||
Package::Package(perm_string n, const ActiveScope&ref)
|
Package::Package(perm_string n, const ActiveScope&ref)
|
||||||
: Scope(ref), name_(n)
|
: Scope(ref), name_(n)
|
||||||
|
|
@ -45,9 +47,14 @@ int Package::elaborate()
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
||||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
for (map<perm_string,SubHeaderList>::iterator cur = cur_subprograms_.begin()
|
||||||
; cur != cur_subprograms_.end() ; ++cur) {
|
; cur != cur_subprograms_.end() ; ++ cur) {
|
||||||
errors += cur->second->elaborate();
|
SubHeaderList& subp_list = cur->second;
|
||||||
|
|
||||||
|
for(SubHeaderList::iterator it = subp_list.begin();
|
||||||
|
it != subp_list.end(); ++it) {
|
||||||
|
errors += (*it)->elaborate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
|
|
@ -108,10 +115,15 @@ void Package::write_to_stream(ostream&fd) const
|
||||||
fd << ";" << endl;
|
fd << ";" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
for (map<perm_string,SubHeaderList>::const_iterator cur = cur_subprograms_.begin()
|
||||||
; cur != cur_subprograms_.end() ; ++cur) {
|
; cur != cur_subprograms_.end() ; ++cur) {
|
||||||
cur->second->write_to_stream(fd);
|
const SubHeaderList& subp_list = cur->second;
|
||||||
fd << ";" << endl;
|
|
||||||
|
for(SubHeaderList::const_iterator it = subp_list.begin();
|
||||||
|
it != subp_list.end(); ++it) {
|
||||||
|
(*it)->write_to_stream(fd);
|
||||||
|
fd << ";" << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (map<perm_string,ComponentBase*>::const_iterator cur = old_components_.begin()
|
for (map<perm_string,ComponentBase*>::const_iterator cur = old_components_.begin()
|
||||||
|
|
@ -128,14 +140,20 @@ void Package::write_to_stream(ostream&fd) const
|
||||||
fd << "end package " << name_ << ";" << endl;
|
fd << "end package " << name_ << ";" << endl;
|
||||||
|
|
||||||
fd << "package body " << name_ << " is" << endl;
|
fd << "package body " << name_ << " is" << endl;
|
||||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
for (map<perm_string,SubHeaderList>::const_iterator cur = cur_subprograms_.begin()
|
||||||
; cur != cur_subprograms_.end() ; ++cur) {
|
; cur != cur_subprograms_.end() ; ++cur) {
|
||||||
SubprogramHeader*subp = cur->second;
|
const SubHeaderList& subp_list = cur->second;
|
||||||
if(subp->body()) {
|
|
||||||
subp->write_to_stream(fd);
|
for(SubHeaderList::const_iterator it = subp_list.begin();
|
||||||
fd << " is" << endl;
|
it != subp_list.end(); ++it) {
|
||||||
subp->body()->write_to_stream(fd);
|
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;
|
fd << "end " << name_ << ";" << endl;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,9 @@
|
||||||
|
|
||||||
# include "package.h"
|
# include "package.h"
|
||||||
# include "subprogram.h"
|
# include "subprogram.h"
|
||||||
# include <iostream>
|
|
||||||
# include "ivl_assert.h"
|
# include "ivl_assert.h"
|
||||||
|
# include <iostream>
|
||||||
|
# include <list>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
@ -64,14 +65,22 @@ int Package::emit_package(ostream&fd) const
|
||||||
//}
|
//}
|
||||||
|
|
||||||
fd << "package \\" << name() << " ;" << endl;
|
fd << "package \\" << name() << " ;" << endl;
|
||||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
for (map<perm_string,SubHeaderList>::const_iterator cur = cur_subprograms_.begin()
|
||||||
; cur != cur_subprograms_.end() ; ++ cur) {
|
; cur != cur_subprograms_.end() ; ++ cur) {
|
||||||
// Do not emit unbounded functions, we will just need fixed instances later
|
const SubHeaderList& subp_list = cur->second;
|
||||||
if(!cur->second->unbounded())
|
|
||||||
errors += cur->second->emit_package(fd);
|
for(SubHeaderList::const_iterator it = subp_list.begin();
|
||||||
else
|
it != subp_list.end(); ++it) {
|
||||||
fd << "/* function " << cur->second->name() <<
|
SubprogramHeader*header = *it;
|
||||||
" has to be instantiated, skipping */" << endl;
|
|
||||||
|
// 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;
|
fd << "endpackage /* " << name() << " */" << endl;
|
||||||
|
|
|
||||||
|
|
@ -1701,7 +1701,8 @@ name /* IEEE 1076-2008 P8.1 */
|
||||||
tmp = parse_char_enums($1);
|
tmp = parse_char_enums($1);
|
||||||
if(!tmp) {
|
if(!tmp) {
|
||||||
perm_string name = lex_strings.make($1);
|
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);
|
tmp = new ExpFunc(name);
|
||||||
else
|
else
|
||||||
tmp = new ExpName(name);
|
tmp = new ExpName(name);
|
||||||
|
|
@ -2565,12 +2566,10 @@ subprogram_body /* IEEE 1076-2008 P4.3 */
|
||||||
K_begin subprogram_statement_part K_end
|
K_begin subprogram_statement_part K_end
|
||||||
subprogram_kind_opt identifier_opt ';'
|
subprogram_kind_opt identifier_opt ';'
|
||||||
{ SubprogramHeader*prog = $1;
|
{ SubprogramHeader*prog = $1;
|
||||||
SubprogramHeader*tmp = active_scope->recall_subprogram(prog->name());
|
SubprogramHeader*tmp = active_scope->recall_subprogram(prog);
|
||||||
if (tmp && prog->compare_specification(tmp)) {
|
if (tmp) {
|
||||||
delete prog;
|
delete prog;
|
||||||
prog = tmp;
|
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();
|
SubprogramBody*body = new SubprogramBody();
|
||||||
|
|
|
||||||
131
vhdlpp/scope.cc
131
vhdlpp/scope.cc
|
|
@ -70,9 +70,14 @@ ScopeBase::ScopeBase(const ActiveScope&ref)
|
||||||
// an active scope and is making the actual scope. At this point
|
// an active scope and is making the actual scope. At this point
|
||||||
// we know that "this" is the parent scope for the subprograms,
|
// we know that "this" is the parent scope for the subprograms,
|
||||||
// so set it now.
|
// so set it now.
|
||||||
for (map<perm_string,SubprogramHeader*>::iterator cur = cur_subprograms_.begin()
|
for (map<perm_string,SubHeaderList>::iterator cur = cur_subprograms_.begin()
|
||||||
; cur != cur_subprograms_.end(); ++cur) {
|
; cur != cur_subprograms_.end(); ++cur) {
|
||||||
cur->second->set_parent(this);
|
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(new_components_);
|
||||||
delete_all(cur_types_);
|
delete_all(cur_types_);
|
||||||
delete_all(cur_constants_);
|
delete_all(cur_constants_);
|
||||||
delete_all(cur_subprograms_);
|
for (map<perm_string,SubHeaderList>::iterator cur = cur_subprograms_.begin()
|
||||||
|
; cur != cur_subprograms_.end() ; ++cur) {
|
||||||
|
delete_all(cur->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VType*ScopeBase::find_type(perm_string by_name)
|
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
|
const InterfacePort* ScopeBase::find_param_all(perm_string by_name) const
|
||||||
{
|
{
|
||||||
for(map<perm_string,SubprogramHeader*>::const_iterator it = use_subprograms_.begin();
|
for(map<perm_string,SubHeaderList>::const_iterator cur = use_subprograms_.begin();
|
||||||
it != use_subprograms_.end(); ++it) {
|
cur != use_subprograms_.end(); ++cur) {
|
||||||
if(const InterfacePort*port = it->second->find_param(by_name))
|
const SubHeaderList& subp_list = cur->second;
|
||||||
return port;
|
|
||||||
|
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<perm_string,SubprogramHeader*>::const_iterator it = cur_subprograms_.begin();
|
for(map<perm_string,SubHeaderList>::const_iterator cur = cur_subprograms_.begin();
|
||||||
it != cur_subprograms_.end(); ++it) {
|
cur != cur_subprograms_.end(); ++cur) {
|
||||||
if(const InterfacePort*port = it->second->find_param(by_name))
|
const SubHeaderList& subp_list = cur->second;
|
||||||
return port;
|
|
||||||
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SubprogramHeader* ScopeBase::find_subprogram(perm_string name) const
|
SubHeaderList ScopeBase::find_subprogram(perm_string name) const
|
||||||
{
|
{
|
||||||
map<perm_string,SubprogramHeader*>::const_iterator cur;
|
map<perm_string,SubHeaderList>::const_iterator cur;
|
||||||
|
|
||||||
cur = cur_subprograms_.find(name);
|
cur = cur_subprograms_.find(name);
|
||||||
if (cur != cur_subprograms_.end())
|
if (cur != cur_subprograms_.end())
|
||||||
return cur->second;
|
return cur->second;
|
||||||
|
|
||||||
cur = use_subprograms_.find(name);
|
cur = use_subprograms_.find(name);
|
||||||
if (cur != use_subprograms_.end())
|
if (cur != use_subprograms_.end())
|
||||||
return cur->second;
|
return cur->second;
|
||||||
|
|
||||||
return find_std_subprogram(name);
|
return find_std_subprogram(name);
|
||||||
}
|
}
|
||||||
|
|
@ -217,9 +235,9 @@ void ScopeBase::do_use_from(const ScopeBase*that)
|
||||||
old_components_[cur->first] = cur->second;
|
old_components_[cur->first] = cur->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = that->cur_subprograms_.begin()
|
for (map<perm_string,SubHeaderList>::const_iterator cur = that->cur_subprograms_.begin()
|
||||||
; cur != that->cur_subprograms_.end() ; ++ cur) {
|
; cur != that->cur_subprograms_.end() ; ++ cur) {
|
||||||
if (cur->second == 0)
|
if (cur->second.empty())
|
||||||
continue;
|
continue;
|
||||||
use_subprograms_[cur->first] = cur->second;
|
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<const VType*>*params) const
|
||||||
|
{
|
||||||
|
int req_param_count = params ? params->size() : 0;
|
||||||
|
|
||||||
|
// Find all subprograms with matching name
|
||||||
|
SubHeaderList l = find_std_subprogram(name);
|
||||||
|
map<perm_string,SubHeaderList>::const_iterator cur;
|
||||||
|
|
||||||
|
cur = use_subprograms_.find(name);
|
||||||
|
if (cur != use_subprograms_.end())
|
||||||
|
copy(cur->second.begin(), cur->second.end(),
|
||||||
|
front_insert_iterator<SubHeaderList>(l));
|
||||||
|
|
||||||
|
cur = cur_subprograms_.find(name);
|
||||||
|
if(cur != cur_subprograms_.end())
|
||||||
|
copy(cur->second.begin(), cur->second.end(),
|
||||||
|
front_insert_iterator<SubHeaderList>(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 VType*>::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)
|
void ActiveScope::set_package_header(Package*pkg)
|
||||||
{
|
{
|
||||||
assert(package_header_ == 0);
|
assert(package_header_ == 0);
|
||||||
package_header_ = pkg;
|
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))
|
list<const VType*> arg_types;
|
||||||
return tmp;
|
SubprogramHeader*tmp;
|
||||||
|
|
||||||
if (package_header_)
|
for(int i = 0; i < subp->param_count(); ++i)
|
||||||
return package_header_->find_subprogram(name);
|
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
|
bool ActiveScope::is_vector_name(perm_string name) const
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ class SubprogramHeader;
|
||||||
class VType;
|
class VType;
|
||||||
class SequentialStmt;
|
class SequentialStmt;
|
||||||
|
|
||||||
|
typedef list<SubprogramHeader*> SubHeaderList;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct delete_object{
|
struct delete_object{
|
||||||
void operator()(T* item) { delete item; }
|
void operator()(T* item) { delete item; }
|
||||||
|
|
@ -59,7 +61,7 @@ class ScopeBase {
|
||||||
Variable* find_variable(perm_string by_name) const;
|
Variable* find_variable(perm_string by_name) const;
|
||||||
virtual const InterfacePort* find_param(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;
|
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
|
// Checks if a string is one of possible enum values. If so, the enum
|
||||||
// type is returned, otherwise NULL.
|
// type is returned, otherwise NULL.
|
||||||
const VTypeEnum* is_enum_name(perm_string name) const;
|
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);
|
void transfer_from(ScopeBase&ref, transfer_type_t what = ALL);
|
||||||
|
|
||||||
inline void bind_subprogram(perm_string name, SubprogramHeader*obj)
|
inline void bind_subprogram(perm_string name, SubprogramHeader*obj)
|
||||||
{ map<perm_string, SubprogramHeader*>::iterator it;
|
{ map<perm_string, SubHeaderList>::iterator it;
|
||||||
if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
|
if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
|
||||||
use_subprograms_.erase(it);
|
it->second.remove(obj);
|
||||||
cur_subprograms_[name] = obj;
|
cur_subprograms_[name].push_back(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a statement to implicit initializers list
|
// Adds a statement to implicit initializers list
|
||||||
|
|
@ -92,6 +94,10 @@ class ScopeBase {
|
||||||
|
|
||||||
void dump_scope(ostream&out) const;
|
void dump_scope(ostream&out) const;
|
||||||
|
|
||||||
|
// Looks for a subprogram with specified name and parameter types.
|
||||||
|
SubprogramHeader*match_subprogram(perm_string name,
|
||||||
|
const list<const VType*>*params) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
|
|
@ -134,8 +140,8 @@ class ScopeBase {
|
||||||
std::map<perm_string, struct const_t*> use_constants_; //imported constants
|
std::map<perm_string, struct const_t*> use_constants_; //imported constants
|
||||||
std::map<perm_string, struct const_t*> cur_constants_; //current constants
|
std::map<perm_string, struct const_t*> cur_constants_; //current constants
|
||||||
|
|
||||||
std::map<perm_string, SubprogramHeader*> use_subprograms_; //imported
|
std::map<perm_string, SubHeaderList> use_subprograms_; //imported
|
||||||
std::map<perm_string, SubprogramHeader*> cur_subprograms_; //current
|
std::map<perm_string, SubHeaderList> cur_subprograms_; //current
|
||||||
|
|
||||||
std::list<const VTypeEnum*> use_enums_;
|
std::list<const VTypeEnum*> use_enums_;
|
||||||
|
|
||||||
|
|
@ -191,7 +197,7 @@ class ActiveScope : public ScopeBase {
|
||||||
// Locate the subprogram by name. The subprogram body uses
|
// Locate the subprogram by name. The subprogram body uses
|
||||||
// this to locate the subprogram declaration. Note that the
|
// this to locate the subprogram declaration. Note that the
|
||||||
// subprogram may be in a package header.
|
// 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
|
/* All bind_name function check if the given name was present
|
||||||
* in previous scopes. If it is found, it is erased (but the pointer
|
* in previous scopes. If it is found, it is erased (but the pointer
|
||||||
|
|
|
||||||
|
|
@ -178,10 +178,22 @@ int ProcedureCall::elaborate(Entity*ent, ScopeBase*scope)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
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<const VType*> arg_types;
|
||||||
|
if(param_list_) {
|
||||||
|
for(list<named_expr_t*>::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_)
|
if(!def_)
|
||||||
def_ = library_find_subprogram(name_);
|
def_ = library_match_subprogram(name_, &arg_types);
|
||||||
|
|
||||||
if(!def_) {
|
if(!def_) {
|
||||||
cerr << get_fileline() << ": error: could not find procedure ";
|
cerr << get_fileline() << ": error: could not find procedure ";
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@
|
||||||
#include "std_types.h"
|
#include "std_types.h"
|
||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
|
|
||||||
static std::map<perm_string,SubprogramHeader*> std_subprograms;
|
static std::map<perm_string,SubHeaderList> std_subprograms;
|
||||||
|
|
||||||
static inline void register_std_subprogram(SubprogramHeader*header)
|
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
|
// Special case: to_integer function
|
||||||
|
|
@ -356,17 +356,20 @@ void preload_std_funcs(void)
|
||||||
|
|
||||||
void delete_std_funcs()
|
void delete_std_funcs()
|
||||||
{
|
{
|
||||||
for(std::map<perm_string,SubprogramHeader*>::iterator it = std_subprograms.begin();
|
for(std::map<perm_string,SubHeaderList>::iterator cur = std_subprograms.begin();
|
||||||
it != std_subprograms.end(); ++it) {
|
cur != std_subprograms.end(); ++cur) {
|
||||||
delete it->second;
|
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<perm_string,SubprogramHeader*>::const_iterator cur = std_subprograms.find(name);
|
map<perm_string,SubHeaderList>::const_iterator cur = std_subprograms.find(name);
|
||||||
if (cur != std_subprograms.end())
|
if(cur != std_subprograms.end())
|
||||||
return cur->second;
|
return cur->second;
|
||||||
|
|
||||||
return NULL;
|
return SubHeaderList();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,6 @@ void preload_std_funcs();
|
||||||
void delete_std_funcs();
|
void delete_std_funcs();
|
||||||
|
|
||||||
// Returns subprogram header for a requested function or NULL if it does not exist.
|
// 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 */
|
#endif /* IVL_std_funcs_H */
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@
|
||||||
class InterfacePort;
|
class InterfacePort;
|
||||||
class SequentialStmt;
|
class SequentialStmt;
|
||||||
class VType;
|
class VType;
|
||||||
class SubprogramHeader;
|
|
||||||
|
|
||||||
class SubprogramBody : public LineInfo, public ScopeBase {
|
class SubprogramBody : public LineInfo, public ScopeBase {
|
||||||
|
|
||||||
|
|
@ -73,6 +72,7 @@ class SubprogramHeader : public LineInfo {
|
||||||
// matches this subprogram and that subprogram.
|
// matches this subprogram and that subprogram.
|
||||||
bool compare_specification(SubprogramHeader*that) const;
|
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*find_param(perm_string nam) const;
|
||||||
const InterfacePort*peek_param(int idx) const;
|
const InterfacePort*peek_param(int idx) const;
|
||||||
const VType*peek_param_type(int idx) const;
|
const VType*peek_param_type(int idx) const;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue