From 25f4a54852c3f28ddde499051bea9a3a73e95adf Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 23 Aug 2016 17:50:57 +0200 Subject: [PATCH] vhdlpp: Subprograms are matched once. ExpFunc::probe_type() return exact type --- vhdlpp/expression.cc | 27 +++++++++++++++++++ vhdlpp/expression.h | 7 +++-- vhdlpp/expression_elaborate.cc | 49 ++++++---------------------------- vhdlpp/subprogram.cc | 18 +++++++++++++ vhdlpp/subprogram.h | 4 +++ 5 files changed, 62 insertions(+), 43 deletions(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 1ecd867f5..b9dff1b91 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -24,6 +24,7 @@ # include "subprogram.h" # include "parse_types.h" # include "scope.h" +# include "library.h" # include # include # include @@ -569,6 +570,32 @@ const VType* ExpFunc::func_ret_type() const return def_ ? def_->peek_return_type() : NULL; } +SubprogramHeader*ExpFunc::match_signature(Entity*ent, ScopeBase*scope) const +{ + SubprogramHeader*prog = NULL; + list arg_types; + + // Create a list of argument types to find a matching subprogram + for(vector::const_iterator it = argv_.begin(); + it != argv_.end(); ++it) { + arg_types.push_back((*it)->probe_type(ent, scope)); + } + + 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; +} + ExpInteger::ExpInteger(int64_t val) : value_(val) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index ca895967e..d31955a89 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -620,12 +620,15 @@ class ExpFunc : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope) const; void dump(ostream&out, int indent = 0) const; - void visit(ExprVisitor& func); // NOTE: does not handle expressions in subprogram + void visit(ExprVisitor& func); // NOTE: does not handle expressions in subprogram body + + // Returns a subprogram header that matches the function call + SubprogramHeader*match_signature(Entity*ent, ScopeBase*scope) const; private: perm_string name_; std::vector argv_; - SubprogramHeader*def_; + mutable SubprogramHeader*def_; }; class ExpInteger : public Expression { diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 171ace8ca..9cd9e057a 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -26,7 +26,6 @@ # include "entity.h" # include "vsignal.h" # include "subprogram.h" -# include "library.h" # include "std_types.h" # include # include @@ -790,55 +789,23 @@ int ExpConditional::case_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VT const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const { - SubprogramHeader*prog = def_; + if(!def_) + def_ = match_signature(ent, scope); - if(!prog) { - list arg_types; - - for(vector::const_iterator it = argv_.begin(); - it != argv_.end(); ++it) { - arg_types.push_back((*it)->probe_type(ent, scope)); - } - - 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(); + return def_ ? def_->exact_return_type(argv_, ent, scope) : NULL; } int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) { int errors = 0; - ivl_assert(*this, def_ == 0); // do not elaborate twice + if(def_) + return 0; - // 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); + def_ = match_signature(ent, scope); if(!def_) - def_ = library_match_subprogram(name_, &arg_types); - - if(!def_) { - cerr << get_fileline() << ": error: could not find function "; - emit_subprogram_sig(cerr, name_, arg_types); - cerr << endl; - return 1; - } + return 1; // Elaborate arguments for (size_t idx = 0; idx < argv_.size(); ++idx) { @@ -858,7 +825,7 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const { - return probe_type(ent, scope); + return probe_type(ent, scope); } const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index bd7d832cc..d06917a31 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -172,6 +172,24 @@ const VType*SubprogramHeader::peek_param_type(int idx) const return NULL; } +const VType*SubprogramHeader::exact_return_type(const std::vector&argv, Entity*ent, ScopeBase*scope) +{ + const VTypeArray*orig_ret = dynamic_cast(return_type_); + + if(!orig_ret) + return return_type_; + + const VTypeArray*arg = dynamic_cast(argv[0]->fit_type(ent, scope, orig_ret)); + + if(!arg) + return return_type_; + + VTypeArray*ret = new VTypeArray(orig_ret->element_type(), arg->dimensions(), orig_ret->signed_vector()); + ret->set_parent_type(orig_ret); + + return ret; +} + bool SubprogramHeader::unbounded() const { if(return_type_ && return_type_->is_unbounded()) return true; diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index d06f82461..a03b8da92 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -80,6 +80,10 @@ class SubprogramHeader : public LineInfo { const VType*peek_param_type(int idx) const; const VType*peek_return_type() const { return return_type_; } + // Computes the exact return type (e.g. std_logic_vector(7 downto 0) + // instead of generic std_logic_vector) + virtual const VType*exact_return_type(const std::vector&, Entity*, ScopeBase*); + inline void set_package(const Package*pkg) { assert(!package_); package_ = pkg; } inline const Package*get_package() const { return package_; }