vhdlpp: Subprograms are matched once. ExpFunc::probe_type() return exact type
This commit is contained in:
parent
8f86004100
commit
25f4a54852
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_; }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue