vhdlpp: Subprograms are matched once. ExpFunc::probe_type() return exact type

This commit is contained in:
Maciej Suminski 2016-08-23 17:50:57 +02:00
parent 8f86004100
commit 25f4a54852
5 changed files with 62 additions and 43 deletions

View File

@ -24,6 +24,7 @@
# include "subprogram.h"
# include "parse_types.h"
# include "scope.h"
# include "library.h"
# include <iostream>
# include <typeinfo>
# include <cstring>
@ -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<const VType*> arg_types;
// Create a list of argument types to find a matching subprogram
for(vector<Expression*>::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)
{

View File

@ -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<Expression*> argv_;
SubprogramHeader*def_;
mutable SubprogramHeader*def_;
};
class ExpInteger : public Expression {

View File

@ -26,7 +26,6 @@
# include "entity.h"
# include "vsignal.h"
# include "subprogram.h"
# include "library.h"
# include "std_types.h"
# include <iostream>
# include <typeinfo>
@ -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<const VType*> arg_types;
for(vector<Expression*>::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<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);
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

View File

@ -172,6 +172,24 @@ const VType*SubprogramHeader::peek_param_type(int idx) const
return NULL;
}
const VType*SubprogramHeader::exact_return_type(const std::vector<Expression*>&argv, Entity*ent, ScopeBase*scope)
{
const VTypeArray*orig_ret = dynamic_cast<const VTypeArray*>(return_type_);
if(!orig_ret)
return return_type_;
const VTypeArray*arg = dynamic_cast<const VTypeArray*>(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;

View File

@ -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<Expression*>&, Entity*, ScopeBase*);
inline void set_package(const Package*pkg) { assert(!package_); package_ = pkg; }
inline const Package*get_package() const { return package_; }