diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 431f7b4f8..fbfa77a18 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -248,6 +248,9 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch children.push_back(child4); fixup_hierarchy_flags(); +#ifdef ASTNODE_GC + Tagger::get().reg(this); +#endif } // create a (deep recursive) copy of a node @@ -283,12 +286,28 @@ void AstNode::cloneInto(AstNode *other) const // delete all children in this node void AstNode::delete_children() { +#ifdef ASTNODE_GC + for (auto &it : children) + if (Tagger::get().nodes.count(it)) + delete it; + else + log("skip child %p\n", it); +#else for (auto &it : children) delete it; +#endif children.clear(); +#ifdef ASTNODE_GC + for (auto &it : attributes) + if (Tagger::get().nodes.count(it.second)) + delete it.second; + else + log("skip attr %p\n", it.second); +#else for (auto &it : attributes) delete it.second; +#endif attributes.clear(); } @@ -296,7 +315,14 @@ void AstNode::delete_children() AstNode::~AstNode() { astnodes--; +#ifdef ASTNODE_GC + Tagger::get().unreg(this); +#endif delete_children(); + if (yosys_xtrace) { + log("DESTR %X %p\n", hashidx_, this); + log_backtrace("", yosys_xtrace-1); + } } // create a nice text representation of the node diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 2c2d408ce..923594a3c 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -467,6 +467,72 @@ namespace AST_INTERNAL AST::AstNode *original_ast = nullptr); } +#undef ASTNODE_GC +#ifdef ASTNODE_GC +struct Tagger { + std::set nodes; + std::set tagged; + static Tagger& get() { + static Tagger instance; + return instance; + } + void reg(AST::AstNode* p) { + if (!p) + return; + log_assert(!nodes.count(p)); + nodes.insert(p); + } + void unreg(AST::AstNode* p) { + if (!p || !nodes.count(p)) + return; + nodes.erase(p); + } + void tag(AST::AstNode* p) { + if (!p) + return; + tagged.insert(p); + for (AST::AstNode* c : p->children) + tag(c); + for (auto x : p->attributes) + tag(x.second); + tag(p->id2ast); + } + void clear() { + tagged.clear(); + } + void dump_untagged() { + Yosys::log("Dumping untagged:\n"); + for (auto p : nodes) { + if (!tagged.count(p)) { + Yosys::log(">> %p\n", p); + p->dumpAst(stdout, ""); + } + } + } + void shadow_kill(AST::AstNode* p) { + if (!p || !nodes.count(p)) + return; + for (AST::AstNode* c : p->children) + shadow_kill(c); + for (auto x : p->attributes) + shadow_kill(x.second); + shadow_kill(p->id2ast); + delete p; + } + void kill_untagged() { + auto copy = nodes; + while (!copy.empty()) { + AST::AstNode* p = *(copy.begin()); + copy.erase(p); + fflush(stdout); + if (!tagged.count(p)) { + shadow_kill(p); + } + } + } +}; +#endif // ASTNODE_GC + YOSYS_NAMESPACE_END #endif diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 14a0f16c0..2e4ea9859 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -39,6 +39,7 @@ YOSYS_NAMESPACE_BEGIN using namespace VERILOG_FRONTEND; + // use the Verilog bison/flex parser to generate an AST and use AST::process() to convert it to RTLIL static std::vector verilog_defaults; @@ -528,7 +529,15 @@ struct VerilogFrontend : public Frontend { AST::process(design, current_ast, flag_nodisplay, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire); +#ifdef ASTNODE_GC + Tagger::get().clear(); + Tagger::get().tag(current_ast); + for (RTLIL::Module* m : design->modules()) + if (AST::AstModule* am = dynamic_cast(m)) + Tagger::get().tag(am->ast); + Tagger::get().dump_untagged(); +#endif if (!flag_nopp) delete lexin; @@ -539,6 +548,9 @@ struct VerilogFrontend : public Frontend { delete current_ast; current_ast = NULL; +#ifdef ASTNODE_GC + Tagger::get().kill_untagged(); +#endif log("Successfully finished Verilog frontend.\n"); }