Fix issue #298: elaborate types in the scope where they were declared.
The compiler elaborates types on the fly as they are used. For user- defined types (typedefs) we must do the elaboration in the scope where the type was declared, not in the scope where it is used.
This commit is contained in:
parent
e8e2c35df0
commit
8dc395940d
|
|
@ -490,6 +490,8 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
|||
use_class->set_definition_scope(scope);
|
||||
set_scope_timescale(des, class_scope, pclass);
|
||||
|
||||
class_scope->add_typedefs(&pclass->typedefs);
|
||||
|
||||
// Elaborate enum types declared in the class. We need these
|
||||
// now because enumeration constants can be used during scope
|
||||
// elaboration.
|
||||
|
|
@ -708,6 +710,8 @@ bool PPackage::elaborate_scope(Design*des, NetScope*scope)
|
|||
<< "Elaborate package " << scope_path(scope) << "." << endl;
|
||||
}
|
||||
|
||||
scope->add_typedefs(&typedefs);
|
||||
|
||||
collect_scope_parameters_(des, scope, parameters);
|
||||
collect_scope_localparams_(des, scope, localparams);
|
||||
|
||||
|
|
@ -734,6 +738,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
|||
<< "Elaborate " << scope_path(scope) << "." << endl;
|
||||
}
|
||||
|
||||
scope->add_typedefs(&typedefs);
|
||||
|
||||
// Add the genvars to the scope.
|
||||
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
||||
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) {
|
||||
|
|
@ -1192,6 +1198,8 @@ void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
|
|||
|
||||
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
{
|
||||
scope->add_typedefs(&typedefs);
|
||||
|
||||
// Add the genvars to this scope.
|
||||
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
||||
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) {
|
||||
|
|
@ -1545,6 +1553,8 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
|
|||
// find otherwise.
|
||||
scope->is_const_func(true);
|
||||
|
||||
scope->add_typedefs(&typedefs);
|
||||
|
||||
// Scan the parameters in the function, and store the information
|
||||
// needed to evaluate the parameter expressions.
|
||||
|
||||
|
|
@ -1563,6 +1573,8 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope->type() == NetScope::TASK);
|
||||
|
||||
scope->add_typedefs(&typedefs);
|
||||
|
||||
// Scan the parameters in the task, and store the information
|
||||
// needed to evaluate the parameter expressions.
|
||||
|
||||
|
|
@ -1611,6 +1623,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
|||
my_scope->set_line(get_file(), get_lineno());
|
||||
my_scope->is_auto(scope->is_auto());
|
||||
my_scope->add_imports(&explicit_imports);
|
||||
my_scope->add_typedefs(&typedefs);
|
||||
|
||||
// Scan the parameters in the scope, and store the information
|
||||
// needed to evaluate the parameter expressions.
|
||||
|
|
|
|||
14
elab_sig.cc
14
elab_sig.cc
|
|
@ -955,6 +955,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
unsigned wid = 1;
|
||||
vector<netrange_t>packed_dimensions;
|
||||
|
||||
NetScope*base_type_scope = scope;
|
||||
if (set_data_type_ && !set_data_type_->name.nil())
|
||||
base_type_scope = scope->find_typedef_scope(des, set_data_type_);
|
||||
|
||||
des->errors += error_cnt_;
|
||||
|
||||
if (port_set_ || net_set_) {
|
||||
|
|
@ -997,7 +1001,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Evaluate ranges for net " << basename() << endl;
|
||||
}
|
||||
dimensions_ok &= evaluate_ranges(des, scope, this, nlist, net_);
|
||||
dimensions_ok &= evaluate_ranges(des, base_type_scope, this, nlist, net_);
|
||||
}
|
||||
assert(net_set_ || net_.empty());
|
||||
|
||||
|
|
@ -1068,6 +1072,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
list<netrange_t>unpacked_dimensions;
|
||||
netdarray_t*netdarray = 0;
|
||||
|
||||
NetScope*array_type_scope = scope;
|
||||
if (uarray_type_ && !uarray_type_->name.nil())
|
||||
array_type_scope = scope->find_typedef_scope(des, uarray_type_);
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
|
||||
; cur != unpacked_.end() ; ++cur) {
|
||||
PExpr*use_lidx = cur->first;
|
||||
|
|
@ -1100,7 +1108,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
ivl_assert(*this, netdarray==0);
|
||||
|
||||
long index_l, index_r;
|
||||
evaluate_range(des, scope, this, *cur, index_l, index_r);
|
||||
evaluate_range(des, array_type_scope, this, *cur, index_l, index_r);
|
||||
|
||||
if (abs(index_r - index_l) > warn_dimension_size) {
|
||||
cerr << get_fileline() << ": warning: Array dimension "
|
||||
|
|
@ -1191,7 +1199,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
|
||||
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
|
||||
const netenum_t*use_enum = scope->find_enumeration_for_name(des, sample_name->name);
|
||||
const netenum_t*use_enum = base_type_scope->find_enumeration_for_name(des, sample_name->name);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
|
|
|
|||
|
|
@ -78,6 +78,11 @@ static void elaborate_array_ranges(Design*des, NetScope*scope,
|
|||
*/
|
||||
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
|
||||
{
|
||||
// User-defined types must be elaborated in the context
|
||||
// where they were defined.
|
||||
if (!name.nil())
|
||||
scope = scope->find_typedef_scope(des, this);
|
||||
|
||||
ivl_assert(*this, scope);
|
||||
Definitions*use_definitions = scope;
|
||||
|
||||
|
|
|
|||
37
net_scope.cc
37
net_scope.cc
|
|
@ -119,6 +119,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_u
|
|||
is_interface_(interface), is_unit_(compilation_unit), unit_(in_unit), up_(up)
|
||||
{
|
||||
imports_ = 0;
|
||||
typedefs_ = 0;
|
||||
events_ = 0;
|
||||
lcounter_ = 0;
|
||||
is_auto_ = false;
|
||||
|
|
@ -224,6 +225,35 @@ NetScope*NetScope::find_import(const Design*des, perm_string name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void NetScope::add_typedefs(const map<perm_string,data_type_t*>*typedefs)
|
||||
{
|
||||
if (!typedefs->empty())
|
||||
typedefs_ = typedefs;
|
||||
}
|
||||
|
||||
NetScope*NetScope::find_typedef_scope(const Design*des, data_type_t*type)
|
||||
{
|
||||
assert(type);
|
||||
|
||||
NetScope *cur_scope = this;
|
||||
while (cur_scope) {
|
||||
if (cur_scope->typedefs_ && cur_scope->typedefs_->find(type->name) != cur_scope->typedefs_->end())
|
||||
return cur_scope;
|
||||
NetScope*import_scope = cur_scope->find_import(des, type->name);
|
||||
if (import_scope)
|
||||
cur_scope = import_scope;
|
||||
else if (cur_scope == unit_)
|
||||
return 0;
|
||||
else
|
||||
cur_scope = cur_scope->parent();
|
||||
|
||||
if (cur_scope == 0)
|
||||
cur_scope = unit_;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the enumeration in the current scope and any parent scopes.
|
||||
*/
|
||||
|
|
@ -235,9 +265,12 @@ const netenum_t*NetScope::find_enumeration_for_name(const Design*des, perm_strin
|
|||
if (tmp) break;
|
||||
NetScope*import_scope = cur_scope->find_import(des, name);
|
||||
if (import_scope)
|
||||
cur_scope = import_scope;
|
||||
cur_scope = import_scope;
|
||||
else if (cur_scope == unit_)
|
||||
return 0;
|
||||
else
|
||||
cur_scope = cur_scope->parent();
|
||||
cur_scope = cur_scope->parent();
|
||||
|
||||
if (cur_scope == 0)
|
||||
cur_scope = unit_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -946,6 +946,11 @@ class NetScope : public Definitions, public Attrib {
|
|||
void add_imports(const map<perm_string,PPackage*>*imports);
|
||||
NetScope*find_import(const Design*des, perm_string name);
|
||||
|
||||
void add_typedefs(const map<perm_string,data_type_t*>*typedefs);
|
||||
|
||||
/* Search the scope hierarchy for the scope where 'type' was defined. */
|
||||
NetScope*find_typedef_scope(const Design*des, data_type_t*type);
|
||||
|
||||
/* Routine to search for the enumeration given a name. It basically
|
||||
* does what enumeration_for_name() does but searched the hierarchy. */
|
||||
const netenum_t*find_enumeration_for_name(const Design*des, perm_string name);
|
||||
|
|
@ -1275,6 +1280,8 @@ class NetScope : public Definitions, public Attrib {
|
|||
|
||||
const map<perm_string,PPackage*>*imports_;
|
||||
|
||||
const map<perm_string,data_type_t*>*typedefs_;
|
||||
|
||||
NetEvent *events_;
|
||||
|
||||
map<perm_string,LineInfo*> genvars_;
|
||||
|
|
|
|||
5
pform.cc
5
pform.cc
|
|
@ -3520,8 +3520,9 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
|||
// Add the file and line information to the enumeration type.
|
||||
FILE_NAME(&(enum_type->li), li);
|
||||
|
||||
// Attach the enumeration to the current scope.
|
||||
pform_put_enum_type_in_scope(enum_type);
|
||||
// If this is an anonymous enumeration, attach it to the current scope.
|
||||
if (enum_type->name.nil())
|
||||
pform_put_enum_type_in_scope(enum_type);
|
||||
|
||||
// Now apply the checked enumeration type to the variables
|
||||
// that are being declared with this type.
|
||||
|
|
|
|||
Loading…
Reference in New Issue