diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index bfa1be9a7..a6bd8f63f 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -268,8 +268,14 @@ bool Subprogram::fixed_return_type(void) (*s)->visit(r); } - const VType*return_type = r.get_type(); + VType*return_type = const_cast(r.get_type()); if(return_type && !return_type->is_unbounded()) { + // Let's check if the variable length can be evaluated without any scope. + // If not, then it is depends on information about e.g. function params + if(return_type->is_variable_length(NULL)) { + if(VTypeArray*arr = dynamic_cast(return_type)) + arr->evaluate_ranges(this); + } return_type_ = return_type; return true; } else { diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index cd4ea42e1..3f2368b5f 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -186,6 +186,19 @@ bool VTypeArray::is_variable_length(ScopeBase*scope) const { return etype_->is_variable_length(scope); } +void VTypeArray::evaluate_ranges(ScopeBase*scope) { + for(std::vector::iterator it = ranges_.begin(); it != ranges_.end(); ++it ) { + int64_t lsb_val = -1, msb_val = -1; + bool dir = it->is_downto(); + + if(it->msb()->evaluate(scope, msb_val) && it->lsb()->evaluate(scope, lsb_val)) { + assert(lsb_val >= 0); + assert(msb_val >= 0); + *it = range_t(new ExpInteger(msb_val), new ExpInteger(lsb_val), dir); + } + } +} + VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val) : base_(base) { diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index b417cbafb..0e602d5ec 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -238,6 +238,10 @@ class VTypeArray : public VType { // To handle subtypes inline void set_parent_type(const VTypeArray*parent) { parent_ = parent; } + // Wherever it is possible, replaces range lsb & msb expressions with + // constant integers. + void evaluate_ranges(ScopeBase*scope); + private: int emit_with_dims_(std::ostream&out, bool packed, perm_string name) const;