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);
|
use_class->set_definition_scope(scope);
|
||||||
set_scope_timescale(des, class_scope, pclass);
|
set_scope_timescale(des, class_scope, pclass);
|
||||||
|
|
||||||
|
class_scope->add_typedefs(&pclass->typedefs);
|
||||||
|
|
||||||
// Elaborate enum types declared in the class. We need these
|
// Elaborate enum types declared in the class. We need these
|
||||||
// now because enumeration constants can be used during scope
|
// now because enumeration constants can be used during scope
|
||||||
// elaboration.
|
// elaboration.
|
||||||
|
|
@ -708,6 +710,8 @@ bool PPackage::elaborate_scope(Design*des, NetScope*scope)
|
||||||
<< "Elaborate package " << scope_path(scope) << "." << endl;
|
<< "Elaborate package " << scope_path(scope) << "." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope->add_typedefs(&typedefs);
|
||||||
|
|
||||||
collect_scope_parameters_(des, scope, parameters);
|
collect_scope_parameters_(des, scope, parameters);
|
||||||
collect_scope_localparams_(des, scope, localparams);
|
collect_scope_localparams_(des, scope, localparams);
|
||||||
|
|
||||||
|
|
@ -734,6 +738,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||||
<< "Elaborate " << scope_path(scope) << "." << endl;
|
<< "Elaborate " << scope_path(scope) << "." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope->add_typedefs(&typedefs);
|
||||||
|
|
||||||
// Add the genvars to the scope.
|
// Add the genvars to the scope.
|
||||||
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
||||||
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) {
|
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)
|
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||||
{
|
{
|
||||||
|
scope->add_typedefs(&typedefs);
|
||||||
|
|
||||||
// Add the genvars to this scope.
|
// Add the genvars to this scope.
|
||||||
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
||||||
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) {
|
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.
|
// find otherwise.
|
||||||
scope->is_const_func(true);
|
scope->is_const_func(true);
|
||||||
|
|
||||||
|
scope->add_typedefs(&typedefs);
|
||||||
|
|
||||||
// Scan the parameters in the function, and store the information
|
// Scan the parameters in the function, and store the information
|
||||||
// needed to evaluate the parameter expressions.
|
// needed to evaluate the parameter expressions.
|
||||||
|
|
||||||
|
|
@ -1563,6 +1573,8 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
assert(scope->type() == NetScope::TASK);
|
assert(scope->type() == NetScope::TASK);
|
||||||
|
|
||||||
|
scope->add_typedefs(&typedefs);
|
||||||
|
|
||||||
// Scan the parameters in the task, and store the information
|
// Scan the parameters in the task, and store the information
|
||||||
// needed to evaluate the parameter expressions.
|
// 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->set_line(get_file(), get_lineno());
|
||||||
my_scope->is_auto(scope->is_auto());
|
my_scope->is_auto(scope->is_auto());
|
||||||
my_scope->add_imports(&explicit_imports);
|
my_scope->add_imports(&explicit_imports);
|
||||||
|
my_scope->add_typedefs(&typedefs);
|
||||||
|
|
||||||
// Scan the parameters in the scope, and store the information
|
// Scan the parameters in the scope, and store the information
|
||||||
// needed to evaluate the parameter expressions.
|
// 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;
|
unsigned wid = 1;
|
||||||
vector<netrange_t>packed_dimensions;
|
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_;
|
des->errors += error_cnt_;
|
||||||
|
|
||||||
if (port_set_ || net_set_) {
|
if (port_set_ || net_set_) {
|
||||||
|
|
@ -997,7 +1001,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||||
<< "Evaluate ranges for net " << basename() << endl;
|
<< "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());
|
assert(net_set_ || net_.empty());
|
||||||
|
|
||||||
|
|
@ -1068,6 +1072,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
list<netrange_t>unpacked_dimensions;
|
list<netrange_t>unpacked_dimensions;
|
||||||
netdarray_t*netdarray = 0;
|
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()
|
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
|
||||||
; cur != unpacked_.end() ; ++cur) {
|
; cur != unpacked_.end() ; ++cur) {
|
||||||
PExpr*use_lidx = cur->first;
|
PExpr*use_lidx = cur->first;
|
||||||
|
|
@ -1100,7 +1108,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
ivl_assert(*this, netdarray==0);
|
ivl_assert(*this, netdarray==0);
|
||||||
|
|
||||||
long index_l, index_r;
|
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) {
|
if (abs(index_r - index_l) > warn_dimension_size) {
|
||||||
cerr << get_fileline() << ": warning: Array dimension "
|
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_)) {
|
} 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();
|
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) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
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)
|
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);
|
ivl_assert(*this, scope);
|
||||||
Definitions*use_definitions = scope;
|
Definitions*use_definitions = scope;
|
||||||
|
|
||||||
|
|
|
||||||
33
net_scope.cc
33
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)
|
is_interface_(interface), is_unit_(compilation_unit), unit_(in_unit), up_(up)
|
||||||
{
|
{
|
||||||
imports_ = 0;
|
imports_ = 0;
|
||||||
|
typedefs_ = 0;
|
||||||
events_ = 0;
|
events_ = 0;
|
||||||
lcounter_ = 0;
|
lcounter_ = 0;
|
||||||
is_auto_ = false;
|
is_auto_ = false;
|
||||||
|
|
@ -224,6 +225,35 @@ NetScope*NetScope::find_import(const Design*des, perm_string name)
|
||||||
return 0;
|
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.
|
* Look for the enumeration in the current scope and any parent scopes.
|
||||||
*/
|
*/
|
||||||
|
|
@ -236,8 +266,11 @@ const netenum_t*NetScope::find_enumeration_for_name(const Design*des, perm_strin
|
||||||
NetScope*import_scope = cur_scope->find_import(des, name);
|
NetScope*import_scope = cur_scope->find_import(des, name);
|
||||||
if (import_scope)
|
if (import_scope)
|
||||||
cur_scope = import_scope;
|
cur_scope = import_scope;
|
||||||
|
else if (cur_scope == unit_)
|
||||||
|
return 0;
|
||||||
else
|
else
|
||||||
cur_scope = cur_scope->parent();
|
cur_scope = cur_scope->parent();
|
||||||
|
|
||||||
if (cur_scope == 0)
|
if (cur_scope == 0)
|
||||||
cur_scope = unit_;
|
cur_scope = unit_;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -946,6 +946,11 @@ class NetScope : public Definitions, public Attrib {
|
||||||
void add_imports(const map<perm_string,PPackage*>*imports);
|
void add_imports(const map<perm_string,PPackage*>*imports);
|
||||||
NetScope*find_import(const Design*des, perm_string name);
|
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
|
/* Routine to search for the enumeration given a name. It basically
|
||||||
* does what enumeration_for_name() does but searched the hierarchy. */
|
* does what enumeration_for_name() does but searched the hierarchy. */
|
||||||
const netenum_t*find_enumeration_for_name(const Design*des, perm_string name);
|
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,PPackage*>*imports_;
|
||||||
|
|
||||||
|
const map<perm_string,data_type_t*>*typedefs_;
|
||||||
|
|
||||||
NetEvent *events_;
|
NetEvent *events_;
|
||||||
|
|
||||||
map<perm_string,LineInfo*> genvars_;
|
map<perm_string,LineInfo*> genvars_;
|
||||||
|
|
|
||||||
3
pform.cc
3
pform.cc
|
|
@ -3520,7 +3520,8 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
||||||
// Add the file and line information to the enumeration type.
|
// Add the file and line information to the enumeration type.
|
||||||
FILE_NAME(&(enum_type->li), li);
|
FILE_NAME(&(enum_type->li), li);
|
||||||
|
|
||||||
// Attach the enumeration to the current scope.
|
// 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);
|
pform_put_enum_type_in_scope(enum_type);
|
||||||
|
|
||||||
// Now apply the checked enumeration type to the variables
|
// Now apply the checked enumeration type to the variables
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue