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,
|
||||
ivl_type_t ntype, unsigned) const
|
||||
{
|
||||
NetENew*obj = new NetENew(ntype);
|
||||
NetExpr*obj = new NetENew(ntype);
|
||||
obj->set_line(*this);
|
||||
|
||||
// Find the constructor for the class. If there is no
|
||||
// constructor then the result of this expression is the
|
||||
// allocation alone.
|
||||
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"));
|
||||
if (new_scope == 0) {
|
||||
// No constructor.
|
||||
|
|
|
|||
|
|
@ -304,12 +304,6 @@ static void elaborate_scope_class(Design*des, NetScope*scope,
|
|||
<< "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
|
||||
// not allowed to escape a class method.
|
||||
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);
|
||||
|
||||
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
|
||||
// signal is also the first argument. For example, the
|
||||
// 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
|
||||
{ // Process a class.
|
||||
pform_end_class_declaration();
|
||||
pform_end_class_declaration(@8);
|
||||
}
|
||||
class_declaration_endlabel_opt
|
||||
{ // 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_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,
|
||||
std::vector<PWire*>*decl, list<string>*table,
|
||||
|
|
|
|||
|
|
@ -111,9 +111,29 @@ PFunction*pform_push_constructor_scope(const struct vlltype&loc)
|
|||
return func;
|
||||
}
|
||||
|
||||
void pform_end_class_declaration(void)
|
||||
void pform_end_class_declaration(const struct vlltype&loc)
|
||||
{
|
||||
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_pop_scope();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue