Elaborate implicit initializers
Remaining pform fixup of property initializers, and elaboration and code generation for implicit constructor.
This commit is contained in:
parent
d346fb098f
commit
75b4b94061
24
elab_expr.cc
24
elab_expr.cc
|
|
@ -4464,13 +4464,35 @@ unsigned PENewClass::test_width(Design*, NetScope*, width_mode_t&)
|
||||||
NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
|
NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
|
||||||
ivl_type_t ntype, unsigned) const
|
ivl_type_t ntype, unsigned) const
|
||||||
{
|
{
|
||||||
NetENew*obj = new NetENew(ntype);
|
NetExpr*obj = new NetENew(ntype);
|
||||||
obj->set_line(*this);
|
obj->set_line(*this);
|
||||||
|
|
||||||
// Find the constructor for the class. If there is no
|
// Find the constructor for the class. If there is no
|
||||||
// constructor then the result of this expression is the
|
// constructor then the result of this expression is the
|
||||||
// allocation alone.
|
// allocation alone.
|
||||||
const netclass_t*ctype = dynamic_cast<const netclass_t*> (ntype);
|
const netclass_t*ctype = dynamic_cast<const netclass_t*> (ntype);
|
||||||
|
|
||||||
|
// If there is an initializer function, then pass the object
|
||||||
|
// through that function first. Note tha the initializer
|
||||||
|
// function has no arguments other then the object itself.
|
||||||
|
if (NetScope*new1_scope = ctype->method_from_name(perm_string::literal("new@"))) {
|
||||||
|
NetFuncDef*def1 = new1_scope->func_def();
|
||||||
|
ivl_assert(*this, def1);
|
||||||
|
ivl_assert(*this, def1->port_count()==1);
|
||||||
|
vector<NetExpr*> parms1 (1);
|
||||||
|
parms1[0] = obj;
|
||||||
|
|
||||||
|
// The return value of the initializer is the "this"
|
||||||
|
// variable, instead of the "new&" scope name.
|
||||||
|
NetNet*res1 = new1_scope->find_signal(perm_string::literal("@"));
|
||||||
|
ivl_assert(*this, res1);
|
||||||
|
|
||||||
|
NetESignal*eres = new NetESignal(res1);
|
||||||
|
NetEUFunc*tmp = new NetEUFunc(scope, new1_scope, eres, parms1, true);
|
||||||
|
tmp->set_line(*this);
|
||||||
|
obj = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
NetScope*new_scope = ctype->method_from_name(perm_string::literal("new"));
|
NetScope*new_scope = ctype->method_from_name(perm_string::literal("new"));
|
||||||
if (new_scope == 0) {
|
if (new_scope == 0) {
|
||||||
// No constructor.
|
// No constructor.
|
||||||
|
|
|
||||||
|
|
@ -304,12 +304,6 @@ static void elaborate_scope_class(Design*des, NetScope*scope,
|
||||||
<< "Elaborate scope class " << pclass->pscope_name() << endl;
|
<< "Elaborate scope class " << pclass->pscope_name() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! use_type->initialize.empty()) {
|
|
||||||
cerr << pclass->get_fileline() << ": sorry: "
|
|
||||||
<< "Class property initializers not supported." << endl;
|
|
||||||
des->errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Class scopes have no parent scope, because references are
|
// Class scopes have no parent scope, because references are
|
||||||
// not allowed to escape a class method.
|
// not allowed to escape a class method.
|
||||||
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),
|
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),
|
||||||
|
|
|
||||||
|
|
@ -538,7 +538,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
elaborate_sig_wires_(des, scope);
|
elaborate_sig_wires_(des, scope);
|
||||||
|
|
||||||
NetNet*ret_sig;
|
NetNet*ret_sig;
|
||||||
if (gn_system_verilog() && fname == "new") {
|
if (gn_system_verilog() && fname=="new" || fname=="new@") {
|
||||||
// Special case: this is a constructor, so the return
|
// Special case: this is a constructor, so the return
|
||||||
// signal is also the first argument. For example, the
|
// signal is also the first argument. For example, the
|
||||||
// source code for the definition may be:
|
// source code for the definition may be:
|
||||||
|
|
|
||||||
2
parse.y
2
parse.y
|
|
@ -673,7 +673,7 @@ class_declaration /* IEEE1800-2005: A.1.2 */
|
||||||
}
|
}
|
||||||
class_items_opt K_endclass
|
class_items_opt K_endclass
|
||||||
{ // Process a class.
|
{ // Process a class.
|
||||||
pform_end_class_declaration();
|
pform_end_class_declaration(@8);
|
||||||
}
|
}
|
||||||
class_declaration_endlabel_opt
|
class_declaration_endlabel_opt
|
||||||
{ // Wrap up the class.
|
{ // Wrap up the class.
|
||||||
|
|
|
||||||
2
pform.h
2
pform.h
|
|
@ -189,7 +189,7 @@ extern void pform_class_property(const struct vlltype&loc,
|
||||||
extern void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net);
|
extern void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net);
|
||||||
extern void pform_set_constructor_return(PFunction*net);
|
extern void pform_set_constructor_return(PFunction*net);
|
||||||
|
|
||||||
extern void pform_end_class_declaration(void);
|
extern void pform_end_class_declaration(const struct vlltype&loc);
|
||||||
|
|
||||||
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
|
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
|
||||||
std::vector<PWire*>*decl, list<string>*table,
|
std::vector<PWire*>*decl, list<string>*table,
|
||||||
|
|
|
||||||
|
|
@ -111,9 +111,29 @@ PFunction*pform_push_constructor_scope(const struct vlltype&loc)
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_end_class_declaration(void)
|
void pform_end_class_declaration(const struct vlltype&loc)
|
||||||
{
|
{
|
||||||
assert(pform_cur_class);
|
assert(pform_cur_class);
|
||||||
|
|
||||||
|
// If there were initializer statements, then collect them
|
||||||
|
// into an implicit constructor function.
|
||||||
|
if (! pform_cur_class->type->initialize.empty()) {
|
||||||
|
PFunction*func = pform_push_function_scope(loc, "new@", true);
|
||||||
|
func->set_ports(0);
|
||||||
|
pform_set_constructor_return(func);
|
||||||
|
pform_set_this_class(loc, func);
|
||||||
|
|
||||||
|
class_type_t*use_class = pform_cur_class->type;
|
||||||
|
if (use_class->initialize.size() == 1) {
|
||||||
|
func->set_statement(use_class->initialize.front());
|
||||||
|
} else {
|
||||||
|
PBlock*tmp = new PBlock(PBlock::BL_SEQ);
|
||||||
|
tmp->set_statement(use_class->initialize);
|
||||||
|
func->set_statement(tmp);
|
||||||
|
}
|
||||||
|
pform_pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
pform_cur_class = 0;
|
pform_cur_class = 0;
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue