Merge pull request #785 from larsclausen/type-ref

Improve handling of type identifier references
This commit is contained in:
Stephen Williams 2022-10-16 20:52:52 -07:00 committed by GitHub
commit c2dbf4e483
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 399 additions and 74 deletions

View File

@ -33,7 +33,7 @@ PWire::PWire(perm_string n,
: name_(n), type_(t), port_type_(pt), data_type_(dt), : name_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), signed_(false),
port_set_(false), net_set_(false), is_scalar_(false), port_set_(false), net_set_(false), is_scalar_(false),
error_cnt_(0), set_data_type_(0), discipline_(0) error_cnt_(0), discipline_(0)
{ {
switch (rt) { switch (rt) {
case SR_PORT: case SR_PORT:
@ -195,8 +195,11 @@ void PWire::set_unpacked_idx(const list<pform_range_t>&ranges)
void PWire::set_data_type(data_type_t*type) void PWire::set_data_type(data_type_t*type)
{ {
assert(set_data_type_ == 0 || set_data_type_ == type); if (set_data_type_.get() == type)
set_data_type_ = type; return;
assert(!set_data_type_.get());
set_data_type_.reset(type);
} }
void PWire::set_discipline(ivl_discipline_t d) void PWire::set_discipline(ivl_discipline_t d)

View File

@ -123,7 +123,7 @@ class PWire : public PNamedItem {
// This is the complex type of the wire. the data_type_ may // This is the complex type of the wire. the data_type_ may
// modify how this is interpreted. // modify how this is interpreted.
data_type_t*set_data_type_; std::unique_ptr<data_type_t> set_data_type_;
ivl_discipline_t discipline_; ivl_discipline_t discipline_;

View File

@ -104,7 +104,7 @@ AS_IF( [test "x$with_m32" = xyes],
[]) [])
CFLAGS="$CTARGETFLAGS $CFLAGS" CFLAGS="$CTARGETFLAGS $CFLAGS"
CXXFLAGS="$CTARGETFLAGS $CXXFLAGS" CXXFLAGS="$CTARGETFLAGS $CXXFLAGS -std=c++11"
LDFLAGS="$CTARGETFLAGS $LDFLAGS" LDFLAGS="$CTARGETFLAGS $LDFLAGS"
# Check that we are using either the GNU compilers or the Sun compilers # Check that we are using either the GNU compilers or the Sun compilers

View File

@ -444,7 +444,7 @@ static void blend_class_constructors(PClass*pclass)
// If we do not have an explicit constructor chain, but there // If we do not have an explicit constructor chain, but there
// is a parent class, then create an implicit chain. // is a parent class, then create an implicit chain.
if (chain_new==0 && pclass->type->base_type!=0) { if (chain_new==0 && pclass->type->base_type) {
chain_new = new PChainConstructor(pclass->type->base_args); chain_new = new PChainConstructor(pclass->type->base_args);
chain_new->set_line(*pclass); chain_new->set_line(*pclass);
} }
@ -512,16 +512,6 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
netclass_t*use_class = new netclass_t(use_type->name, use_base_class); netclass_t*use_class = new netclass_t(use_type->name, use_base_class);
// If this is a package we need to remember the elaborated type so that
// scoped type references work. Since there is only one instance for each
// package this works. For classes defined in modules there might be
// multiple instances though. Each module instance will have its own class
// type instance, so the same does not work there.
if (scope->type() == NetScope::PACKAGE) {
ivl_assert(*pclass, use_type->save_elaborated_type == 0);
use_type->save_elaborated_type = use_class;
}
NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()), NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()),
NetScope::CLASS, scope->unit()); NetScope::CLASS, scope->unit());
class_scope->set_line(pclass); class_scope->set_line(pclass);

View File

@ -939,10 +939,10 @@ bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope, ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope,
const std::vector<netrange_t>&packed_dimensions) const const std::vector<netrange_t>&packed_dimensions) const
{ {
if (set_data_type_ && !dynamic_cast<vector_type_t*>(set_data_type_)) { vector_type_t *vec_type = dynamic_cast<vector_type_t*>(set_data_type_.get());
ivl_type_t use_type = set_data_type_->elaborate_type(des, scope); if (set_data_type_ && !vec_type) {
ivl_assert(*this, packed_dimensions.empty()); ivl_assert(*this, packed_dimensions.empty());
return use_type; return set_data_type_->elaborate_type(des, scope);
} }
// Fallback method. Create vector type. // Fallback method. Create vector type.
@ -1003,10 +1003,6 @@ 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 *type_scope = scope;
if (set_data_type_ && !set_data_type_->name.nil())
type_scope = type_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_) {
@ -1046,7 +1042,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, type_scope, this, nlist, net_); dimensions_ok &= evaluate_ranges(des, scope, this, nlist, net_);
} }
assert(net_set_ || net_.empty()); assert(net_set_ || net_.empty());
@ -1147,10 +1143,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
wtype = NetNet::WIRE; wtype = NetNet::WIRE;
} }
ivl_type_t type = elaborate_type(des, type_scope, packed_dimensions); ivl_type_t type = elaborate_type(des, scope, packed_dimensions);
// Create the type for the unpacked dimensions. If the // Create the type for the unpacked dimensions. If the
// unpacked_dimensions are empty this will just return the base type. // unpacked_dimensions are empty this will just return the base type.
type = elaborate_array_type(des, type_scope, *this, type, unpacked_); type = elaborate_array_type(des, scope, *this, type, unpacked_);
list<netrange_t> unpacked_dimensions; list<netrange_t> unpacked_dimensions;
// If this is an unpacked array extract the base type and unpacked // If this is an unpacked array extract the base type and unpacked

View File

@ -18,6 +18,7 @@
*/ */
# include "PExpr.h" # include "PExpr.h"
# include "PScope.h"
# include "pform_types.h" # include "pform_types.h"
# include "netlist.h" # include "netlist.h"
# include "netclass.h" # include "netclass.h"
@ -40,10 +41,7 @@ using namespace std;
*/ */
ivl_type_t data_type_t::elaborate_type(Design*des, NetScope*scope) ivl_type_t data_type_t::elaborate_type(Design*des, NetScope*scope)
{ {
// User-defined types must be elaborated in the context scope = find_scope(des, scope);
// 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;
@ -57,6 +55,11 @@ ivl_type_t data_type_t::elaborate_type(Design*des, NetScope*scope)
return tmp; return tmp;
} }
NetScope *data_type_t::find_scope(Design *, NetScope *scope) const
{
return scope;
}
ivl_type_t data_type_t::elaborate_type_raw(Design*des, NetScope*) const ivl_type_t data_type_t::elaborate_type_raw(Design*des, NetScope*) const
{ {
cerr << get_fileline() << ": internal error: " cerr << get_fileline() << ": internal error: "
@ -112,8 +115,6 @@ ivl_type_t atom_type_t::elaborate_type_raw(Design*des, NetScope*) const
ivl_type_t class_type_t::elaborate_type_raw(Design*des, NetScope*scope) const ivl_type_t class_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{ {
if (save_elaborated_type)
return save_elaborated_type;
return scope->find_class(des, name); return scope->find_class(des, name);
} }
@ -366,3 +367,26 @@ ivl_type_t uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
return elaborate_array_type(des, scope, *this, btype, *dims.get()); return elaborate_array_type(des, scope, *this, btype, *dims.get());
} }
ivl_type_t typeref_t::elaborate_type_raw(Design*des, NetScope*s) const
{
if (!s) {
// Try to recover
return new netvector_t(IVL_VT_LOGIC);
}
return type->elaborate_type(des, s);
}
NetScope *typeref_t::find_scope(Design *des, NetScope *s) const
{
// If a scope has been specified use that as a starting point for the
// search
if (scope)
s = des->find_package(scope->pscope_name());
if (!type->name.nil())
s = s->find_typedef_scope(des, type);
return s;
}

View File

@ -0,0 +1,29 @@
// Check that a packed array type identifier used for a module port is
// elaborated in the correct scope.
localparam A = 2;
typedef logic [A-1:0] T;
module test (
input T x
);
localparam A = 5;
bit failed = 1'b0;
`define check(expr, val) \
if (expr !== val) begin \
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
failed = 1'b1; \
end
initial begin
`check($bits(x), 2);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,26 @@
// Check that it is possible to reference a package scoped type identifier as
// the type in a type cast expression.
bit failed = 1'b0;
`define check(expr, val) \
if (expr !== val) begin \
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
failed = 1'b1; \
end
package P;
typedef integer T;
endpackage
module test;
integer x;
initial begin
x = P::T'(-1024.123);
`check(x, -1024)
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,28 @@
// Check that it is possible to reference a package scoped type identifier as
// the type in a type cast expression, even if there is a identifier of the same
// name in the local scope.
bit failed = 1'b0;
`define check(expr, val) \
if (expr !== val) begin \
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
failed = 1'b1; \
end
package P;
typedef integer T;
endpackage
module test;
localparam T = 2;
integer x;
initial begin
x = P::T'(-1024.123);
`check(x, -1024)
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,39 @@
// Check that class types declared in a package can be referenced using a scoped
// type identifier.
bit failed = 1'b0;
`define check(expr, val) \
if (expr !== val) begin \
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
failed = 1'b1; \
end
package P;
localparam A = 8;
class C;
logic [A-1:0] x;
task t;
`check($bits(x), 8)
if (!failed) begin
$display("PASSED");
end
endtask
endclass
endpackage
module test;
localparam A = 4;
P::C c;
initial begin
c = new;
c.t();
end
endmodule

View File

@ -0,0 +1,38 @@
// Check that enum types declared in a package can be referenced using a scoped
// type identifier.
bit failed = 1'b0;
`define check(expr, val) \
if (expr !== val) begin \
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
failed = 1'b1; \
end
package P;
localparam X = 8;
typedef enum logic [X-1:0] {
A, B = X
} T;
endpackage
module test;
localparam X = 4;
typedef int T;
P::T x = P::B;
initial begin
`check(x, P::B)
`check(x, 8)
`check($bits(x), 8);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,24 @@
// Check that it is possible to reference a package scoped type identifier in an
// expression.
bit failed = 1'b0;
`define check(expr, val) \
if (expr !== val) begin \
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
failed = 1'b1; \
end
package P;
typedef integer T;
endpackage
module test;
initial begin
`check($bits(P::T), $bits(integer))
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,26 @@
// Check that it is possible to reference a package scoped type identifier in an
// expression, even if there is a non type identifier of the same name in the
// current scope.
bit failed = 1'b0;
`define check(expr, val) \
if (expr !== val) begin \
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
failed = 1'b1; \
end
package P;
typedef integer T;
endpackage
module test;
integer T;
initial begin
`check($bits(P::T), $bits(integer))
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,40 @@
// Check that struct types declared in a package can be referenced using a
// scoped type identifier.
bit failed = 1'b0;
`define check(expr, val) \
if (expr !== val) begin \
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
failed = 1'b1; \
end
package P;
localparam A = 8;
typedef struct packed {
logic [A-1:0] x;
} T;
endpackage
typedef int T;
module test;
localparam A = 4;
typedef int T;
P::T x;
initial begin
x = 8'hff;
`check(x, 8'hff)
`check($bits(x), 8)
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,51 @@
// Check that chained type definitions declared in different scopes work
// correctly.
package P1;
localparam A = 8;
typedef logic [A-1:0] T;
endpackage
package P2;
localparam A = 4;
typedef P1::T T;
endpackage
bit failed = 1'b0;
`define check(expr, val) \
if (expr !== val) begin \
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
failed = 1'b1; \
end
module test;
localparam A = 2;
typedef P2::T T;
T x;
P1::T y;
P2::T z;
initial begin
x = 8'hff;
y = 8'hff;
z = 8'hff;
`check(x, 8'hff);
`check($bits(T), 8);
`check($bits(x), 8);
`check(y, 8'hff);
`check($bits(y), 8);
`check($bits(P1::T), 8);
`check(z, 8'hff);
`check($bits(z), 8);
`check($bits(P2::T), 8);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -372,6 +372,7 @@ module_nonansi_struct_fail CE,-g2005-sv ivltests
module_output_port_sv_var1 normal,-g2005-sv ivltests module_output_port_sv_var1 normal,-g2005-sv ivltests
module_output_port_sv_var2 normal,-g2005-sv ivltests module_output_port_sv_var2 normal,-g2005-sv ivltests
module_port_typedef_array1 normal,-g2005-sv ivltests module_port_typedef_array1 normal,-g2005-sv ivltests
module_port_typedef_vector normal,-g2005-sv ivltests
named_begin normal,-g2009 ivltests named_begin normal,-g2009 ivltests
named_begin_fail CE,-g2009 ivltests named_begin_fail CE,-g2009 ivltests
named_fork normal,-g2009 ivltests named_fork normal,-g2009 ivltests
@ -634,6 +635,13 @@ sv_ps_function2 normal,-g2009 ivltests
sv_ps_function3 normal,-g2009 ivltests sv_ps_function3 normal,-g2009 ivltests
sv_ps_function4 normal,-g2009 ivltests sv_ps_function4 normal,-g2009 ivltests
sv_ps_type1 normal,-g2009 ivltests sv_ps_type1 normal,-g2009 ivltests
sv_ps_type_cast1 normal,-g2009 ivltests
sv_ps_type_cast2 normal,-g2009 ivltests
sv_ps_type_class1 normal,-g2009 ivltests
sv_ps_type_enum1 normal,-g2009 ivltests
sv_ps_type_expr1 normal,-g2009 ivltests
sv_ps_type_expr2 normal,-g2009 ivltests
sv_ps_type_struct1 normal,-g2009 ivltests
sv_ps_var1 normal,-g2009 ivltests sv_ps_var1 normal,-g2009 ivltests
sv_queue1 normal,-g2009 ivltests sv_queue1 normal,-g2009 ivltests
sv_queue2 normal,-g2009 ivltests sv_queue2 normal,-g2009 ivltests
@ -705,6 +713,7 @@ sv_typedef_array_base1 normal,-g2009 ivltests
sv_typedef_array_base2 normal,-g2009 ivltests sv_typedef_array_base2 normal,-g2009 ivltests
sv_typedef_array_base3 normal,-g2009 ivltests sv_typedef_array_base3 normal,-g2009 ivltests
sv_typedef_array_base4 normal,-g2009 ivltests sv_typedef_array_base4 normal,-g2009 ivltests
sv_typedef_chained normal,-g2009 ivltests
sv_typedef_darray_base1 normal,-g2009 ivltests sv_typedef_darray_base1 normal,-g2009 ivltests
sv_typedef_darray_base2 normal,-g2009 ivltests sv_typedef_darray_base2 normal,-g2009 ivltests
sv_typedef_darray_base3 normal,-g2009 ivltests sv_typedef_darray_base3 normal,-g2009 ivltests

View File

@ -438,6 +438,7 @@ sv_port_default6 CE,-g2009,-pallowsigned=1 ivltests
sv_port_default7 CE,-g2009,-pallowsigned=1 ivltests sv_port_default7 CE,-g2009,-pallowsigned=1 ivltests
sv_port_default8 CE,-g2009,-pallowsigned=1 ivltests sv_port_default8 CE,-g2009,-pallowsigned=1 ivltests
sv_port_default9 CE,-g2009 ivltests sv_port_default9 CE,-g2009 ivltests
sv_ps_type_class1 CE,-g2009 ivltests
sv_root_class CE,-g2009 ivltests sv_root_class CE,-g2009 ivltests
sv_typedef_scope3 CE,-g2009 ivltests sv_typedef_scope3 CE,-g2009 ivltests
sv_unit2b CE,-g2009 ivltests sv_unit2b CE,-g2009 ivltests

View File

@ -23,10 +23,6 @@
# include <typeinfo> # include <typeinfo>
# include "ivl_assert.h" # include "ivl_assert.h"
#if __cplusplus < 201103L
#define unique_ptr auto_ptr
#endif
using namespace std; using namespace std;
/* /*

26
parse.y
View File

@ -28,6 +28,7 @@
# include "pform.h" # include "pform.h"
# include "Statement.h" # include "Statement.h"
# include "PSpec.h" # include "PSpec.h"
# include "PPackage.h"
# include <stack> # include <stack>
# include <cstring> # include <cstring>
# include <sstream> # include <sstream>
@ -825,20 +826,9 @@ class_identifier
the class name is detected by the lexor as a TYPE_IDENTIFIER if it the class name is detected by the lexor as a TYPE_IDENTIFIER if it
does indeed match a name. */ does indeed match a name. */
class_declaration_endlabel_opt class_declaration_endlabel_opt
: ':' TYPE_IDENTIFIER : ':' TYPE_IDENTIFIER { $$ = $2.text; }
{ class_type_t*tmp = dynamic_cast<class_type_t*> ($2.type); | ':' IDENTIFIER { $$ = $2; }
if (tmp == 0) { | { $$ = 0; }
yyerror(@2, "error: class declaration endlabel \"%s\" is not a class name\n", $2.text);
$$ = 0;
} else {
$$ = strdupnew(tmp->name.str());
}
delete[]$2.text;
}
| ':' IDENTIFIER
{ $$ = $2; }
|
{ $$ = 0; }
; ;
/* This rule implements [ extends class_type ] in the /* This rule implements [ extends class_type ] in the
@ -1179,12 +1169,14 @@ ps_type_identifier /* IEEE1800-2017: A.9.3 */
: TYPE_IDENTIFIER : TYPE_IDENTIFIER
{ pform_set_type_referenced(@1, $1.text); { pform_set_type_referenced(@1, $1.text);
delete[]$1.text; delete[]$1.text;
$$ = $1.type; $$ = new typeref_t($1.type);
FILE_NAME($$, @1);
} }
| package_scope TYPE_IDENTIFIER | package_scope TYPE_IDENTIFIER
{ lex_in_package_scope(0); { lex_in_package_scope(0);
$$ = $2.type; $$ = new typeref_t($2.type, $1);
delete[]$2.text; FILE_NAME($$, @2);
delete[] $2.text;
} }
; ;

View File

@ -173,6 +173,15 @@ ostream& data_type_t::debug_dump(ostream&out) const
return out; return out;
} }
std::ostream& typeref_t::debug_dump(ostream&out) const
{
if (scope)
out << scope->pscope_name() << "::";
out << type->name;
return out;
}
ostream& atom_type_t::debug_dump(ostream&out) const ostream& atom_type_t::debug_dump(ostream&out) const
{ {
if (signed_flag) if (signed_flag)

View File

@ -51,7 +51,7 @@ void pform_start_class_declaration(const struct vlltype&loc,
pform_cur_class = class_scope; pform_cur_class = class_scope;
assert(type->base_type == 0); assert(type->base_type == 0);
type->base_type = base_type; type->base_type.reset(base_type);
assert(type->base_args.empty()); assert(type->base_args.empty());
if (base_exprs) { if (base_exprs) {

View File

@ -33,10 +33,6 @@
# include <map> # include <map>
# include <memory> # include <memory>
#if __cplusplus < 201103L
#define unique_ptr auto_ptr
#endif
/* /*
* parse-form types. * parse-form types.
*/ */
@ -45,6 +41,7 @@ class Design;
class NetScope; class NetScope;
class Definitions; class Definitions;
class PExpr; class PExpr;
class PScope;
class PWire; class PWire;
class Statement; class Statement;
class netclass_t; class netclass_t;
@ -165,6 +162,8 @@ class data_type_t : public PNamedItem {
virtual SymbolType symbol_type() const; virtual SymbolType symbol_type() const;
virtual NetScope *find_scope(Design* des, NetScope *scope) const;
perm_string name; perm_string name;
private: private:
@ -175,6 +174,19 @@ class data_type_t : public PNamedItem {
std::map<Definitions*,ivl_type_t> cache_type_elaborate_; std::map<Definitions*,ivl_type_t> cache_type_elaborate_;
}; };
struct typeref_t : public data_type_t {
explicit typeref_t(data_type_t *t, PScope *s = 0) : scope(s), type(t) {}
ivl_type_t elaborate_type_raw(Design*des, NetScope*scope) const;
NetScope *find_scope(Design* des, NetScope *scope) const;
std::ostream& debug_dump(std::ostream&out) const;
private:
PScope *scope;
data_type_t *type;
};
struct void_type_t : public data_type_t { struct void_type_t : public data_type_t {
virtual void pform_dump(std::ostream&out, unsigned indent) const; virtual void pform_dump(std::ostream&out, unsigned indent) const;
}; };
@ -193,7 +205,7 @@ struct enum_type_t : public data_type_t {
SymbolType symbol_type() const; SymbolType symbol_type() const;
data_type_t *base_type; std::unique_ptr<data_type_t> base_type;
std::unique_ptr< std::list<named_pexpr_t> > names; std::unique_ptr< std::list<named_pexpr_t> > names;
}; };
@ -270,7 +282,7 @@ struct array_base_t : public data_type_t {
inline explicit array_base_t(data_type_t*btype, std::list<pform_range_t>*pd) inline explicit array_base_t(data_type_t*btype, std::list<pform_range_t>*pd)
: base_type(btype), dims(pd) { } : base_type(btype), dims(pd) { }
data_type_t*base_type; std::unique_ptr<data_type_t> base_type;
std::unique_ptr< std::list<pform_range_t> > dims; std::unique_ptr< std::list<pform_range_t> > dims;
}; };
@ -323,8 +335,7 @@ struct string_type_t : public data_type_t {
struct class_type_t : public data_type_t { struct class_type_t : public data_type_t {
inline explicit class_type_t(perm_string n) inline explicit class_type_t(perm_string n) { name = n; }
: base_type(0), save_elaborated_type(0) { name = n; }
void pform_dump(std::ostream&out, unsigned indent) const; void pform_dump(std::ostream&out, unsigned indent) const;
void pform_dump_init(std::ostream&out, unsigned indent) const; void pform_dump_init(std::ostream&out, unsigned indent) const;
@ -333,15 +344,17 @@ struct class_type_t : public data_type_t {
// class that we are extending. This is nil if there is no // class that we are extending. This is nil if there is no
// hierarchy. If there are arguments to the base class, then // hierarchy. If there are arguments to the base class, then
// put them in the base_args vector. // put them in the base_args vector.
data_type_t*base_type; std::unique_ptr<data_type_t> base_type;
std::list<PExpr*>base_args; std::list<PExpr*>base_args;
// This is a map of the properties. Map the name to the type. // This is a map of the properties. Map the name to the type.
struct prop_info_t : public LineInfo { struct prop_info_t : public LineInfo {
inline prop_info_t() : qual(property_qualifier_t::make_none()), type(0) { } inline prop_info_t() : qual(property_qualifier_t::make_none()) { }
inline prop_info_t(property_qualifier_t q, data_type_t*t) : qual(q), type(t) { } inline prop_info_t(property_qualifier_t q, data_type_t*t) : qual(q), type(t) { }
prop_info_t(prop_info_t&&) = default;
prop_info_t& operator=(prop_info_t&&) = default;
property_qualifier_t qual; property_qualifier_t qual;
data_type_t* type; std::unique_ptr<data_type_t> type;
}; };
std::map<perm_string, struct prop_info_t> properties; std::map<perm_string, struct prop_info_t> properties;
@ -356,11 +369,6 @@ struct class_type_t : public data_type_t {
std::vector<Statement*> initialize_static; std::vector<Statement*> initialize_static;
ivl_type_t elaborate_type_raw(Design*, NetScope*) const; ivl_type_t elaborate_type_raw(Design*, NetScope*) const;
// The save_elaborated_type member must be set to the pointer
// to the netclass_t object that is created to represent this
// type. The elaborate_type_raw() method uses this pointer,
// and it is used in some other situations as well.
netclass_t* save_elaborated_type;
virtual SymbolType symbol_type() const; virtual SymbolType symbol_type() const;
}; };
@ -425,8 +433,4 @@ extern std::ostream& operator<< (std::ostream&out, const pform_name_t&);
extern std::ostream& operator<< (std::ostream&out, const name_component_t&that); extern std::ostream& operator<< (std::ostream&out, const name_component_t&that);
extern std::ostream& operator<< (std::ostream&out, const index_component_t&that); extern std::ostream& operator<< (std::ostream&out, const index_component_t&that);
#if __cplusplus < 201103L
#undef unique_ptr
#endif
#endif /* IVL_pform_types_H */ #endif /* IVL_pform_types_H */