fix memory leaks of AstNode objects Co-authored-by: Mariusz Glebocki <mglebocki@antmicro.com>
diff --git a/systemverilog-plugin/UhdmAst.cc b/systemverilog-plugin/UhdmAst.cc index 40e80cd..0917e1a 100644 --- a/systemverilog-plugin/UhdmAst.cc +++ b/systemverilog-plugin/UhdmAst.cc
@@ -4,6 +4,7 @@ #include <limits> #include <regex> #include <string> +#include <utility> #include <vector> #include "UhdmAst.h" @@ -95,6 +96,46 @@ attr_id::partial = IdString(); } +// Delete the selected attribute if it exists. +// Does nothing if the node doesn't exist, or the attribute doesn't exists. +static void delete_attribute(AST::AstNode *node, const IdString &attribute) +{ + if (!node) + return; + + if (node->attributes.count(attribute)) { + delete node->attributes[attribute]; + node->attributes.erase(attribute); + } +} + +// Delete all attributes that belong to the SV plugin. +// The attributes beloning to Yosys are *not* deleted here. +static void delete_internal_attributes(AST::AstNode *node) +{ + if (!node) + return; + + for (auto &attr : {UhdmAst::partial(), UhdmAst::packed_ranges(), UhdmAst::unpacked_ranges(), UhdmAst::force_convert(), UhdmAst::is_imported(), + UhdmAst::is_simplified_wire(), UhdmAst::low_high_bound()}) { + delete_attribute(node, attr); + } +} + +// Delete all children nodes. +// Does *not* delete attributes. +// This function exists as Yosys's function node->delete_children() does remove all children and attributes. +static void delete_children(AST::AstNode *node) +{ + if (!node) + return; + + for (auto *child : node->children) { + delete child; + } + node->children.clear(); +} + static void sanitize_symbol_name(std::string &name) { if (!name.empty()) { @@ -207,20 +248,20 @@ static void add_multirange_wire(AST::AstNode *node, std::vector<AST::AstNode *> packed_ranges, std::vector<AST::AstNode *> unpacked_ranges, bool reverse = true) { + delete_attribute(node, UhdmAst::packed_ranges()); node->attributes[UhdmAst::packed_ranges()] = AST::AstNode::mkconst_int(1, false, 1); if (!packed_ranges.empty()) { if (reverse) std::reverse(packed_ranges.begin(), packed_ranges.end()); - node->attributes[UhdmAst::packed_ranges()]->children.insert(node->attributes[UhdmAst::packed_ranges()]->children.end(), packed_ranges.begin(), - packed_ranges.end()); + node->attributes[UhdmAst::packed_ranges()]->children = std::move(packed_ranges); } + delete_attribute(node, UhdmAst::unpacked_ranges()); node->attributes[UhdmAst::unpacked_ranges()] = AST::AstNode::mkconst_int(1, false, 1); if (!unpacked_ranges.empty()) { if (reverse) std::reverse(unpacked_ranges.begin(), unpacked_ranges.end()); - node->attributes[UhdmAst::unpacked_ranges()]->children.insert(node->attributes[UhdmAst::unpacked_ranges()]->children.end(), - unpacked_ranges.begin(), unpacked_ranges.end()); + node->attributes[UhdmAst::unpacked_ranges()]->children = std::move(unpacked_ranges); } } @@ -261,8 +302,7 @@ return size; } -static AST::AstNode *convert_range(AST::AstNode *id, const std::vector<AST::AstNode *> packed_ranges, - const std::vector<AST::AstNode *> unpacked_ranges, int i) +static AST::AstNode *convert_range(AST::AstNode *id, int packed_ranges_size, int unpacked_ranges_size, int i) { log_assert(AST_INTERNAL::current_ast_mod); log_assert(AST_INTERNAL::current_scope.count(id->str)); @@ -276,12 +316,12 @@ single_elem_size.push_back(elem_size); } std::reverse(single_elem_size.begin(), single_elem_size.end()); - log_assert(i < static_cast<int>(unpacked_ranges.size() + packed_ranges.size())); + log_assert(i < (unpacked_ranges_size + packed_ranges_size)); log_assert(!id->children.empty()); AST::AstNode *result = nullptr; // we want to start converting from the end if (i < static_cast<int>(id->children.size()) - 1) { - result = convert_range(id, packed_ranges, unpacked_ranges, i + 1); + result = convert_range(id, packed_ranges_size, unpacked_ranges_size, i + 1); } // special case, we want to select whole wire if (id->children.size() == 0 && i == 0) { @@ -302,8 +342,8 @@ if (is_swapped) { auto left_idx = wire_node->multirange_dimensions.size() - (i * 2) - 1; auto elem_size = wire_node->multirange_dimensions[left_idx] - wire_node->multirange_dimensions[right_idx]; - range_left = new AST::AstNode(AST::AST_SUB, AST::AstNode::mkconst_int(elem_size - 1, false), range_left->clone()); - range_right = new AST::AstNode(AST::AST_SUB, AST::AstNode::mkconst_int(elem_size - 1, false), range_right->clone()); + range_left = new AST::AstNode(AST::AST_SUB, AST::AstNode::mkconst_int(elem_size - 1, false), range_left); + range_right = new AST::AstNode(AST::AST_SUB, AST::AstNode::mkconst_int(elem_size - 1, false), range_right); } else if (wire_node->multirange_dimensions[right_idx] != 0) { range_left = new AST::AstNode(AST::AST_SUB, range_left, AST::AstNode::mkconst_int(wire_node->multirange_dimensions[right_idx], false)); @@ -311,16 +351,17 @@ new AST::AstNode(AST::AST_SUB, range_right, AST::AstNode::mkconst_int(wire_node->multirange_dimensions[right_idx], false)); } } - range_left = - new AST::AstNode(AST::AST_SUB, - new AST::AstNode(AST::AST_MUL, new AST::AstNode(AST::AST_ADD, range_left->clone(), AST::AstNode::mkconst_int(1, false)), - AST::AstNode::mkconst_int(single_elem_size[i + 1], false)), - AST::AstNode::mkconst_int(1, false)); - range_right = new AST::AstNode(AST::AST_MUL, range_right->clone(), AST::AstNode::mkconst_int(single_elem_size[i + 1], false)); + range_left = new AST::AstNode(AST::AST_SUB, + new AST::AstNode(AST::AST_MUL, new AST::AstNode(AST::AST_ADD, range_left, AST::AstNode::mkconst_int(1, false)), + AST::AstNode::mkconst_int(single_elem_size[i + 1], false)), + AST::AstNode::mkconst_int(1, false)); + range_right = new AST::AstNode(AST::AST_MUL, range_right, AST::AstNode::mkconst_int(single_elem_size[i + 1], false)); if (result) { - range_right = new AST::AstNode(AST::AST_ADD, range_right->clone(), result->children[1]->clone()); + range_right = new AST::AstNode(AST::AST_ADD, range_right, result->children[1]->clone()); range_left = new AST::AstNode(AST::AST_SUB, new AST::AstNode(AST::AST_ADD, range_right->clone(), result->children[0]->clone()), result->children[1]->clone()); + delete result; + result = nullptr; } result = new AST::AstNode(AST::AST_RANGE, range_left, range_right); } @@ -387,9 +428,9 @@ } } else { if (wire_node->children[0]->type == AST::AST_RANGE) - packed_ranges.push_back(wire_node->children[0]); + packed_ranges.push_back(wire_node->children[0]->clone()); else if (wire_node->children[1]->type == AST::AST_RANGE) - packed_ranges.push_back(wire_node->children[1]); + packed_ranges.push_back(wire_node->children[1]->clone()); else log_error("Unhandled case in resolve_wiretype!\n"); } @@ -397,7 +438,7 @@ if (wire_node->children[0]->type != AST::AST_RANGE) { value = wire_node->children[0]->clone(); } - wire_node->children.clear(); + delete_children(wire_node); if (value) wire_node->children.push_back(value); wire_node->attributes[UhdmAst::packed_ranges()] = AST::AstNode::mkconst_int(1, false, 1); @@ -405,14 +446,22 @@ std::reverse(packed_ranges.begin(), packed_ranges.end()); wire_node->attributes[UhdmAst::packed_ranges()]->children.insert(wire_node->attributes[UhdmAst::packed_ranges()]->children.end(), packed_ranges.begin(), packed_ranges.end()); + packed_ranges.clear(); } wire_node->attributes[UhdmAst::unpacked_ranges()] = AST::AstNode::mkconst_int(1, false, 1); if (!unpacked_ranges.empty()) { wire_node->attributes[UhdmAst::unpacked_ranges()]->children.insert(wire_node->attributes[UhdmAst::unpacked_ranges()]->children.end(), unpacked_ranges.begin(), unpacked_ranges.end()); + unpacked_ranges.clear(); } } + for (auto *range : packed_ranges) { + delete range; + } + for (auto *range : unpacked_ranges) { + delete range; + } } static void add_force_convert_attribute(AST::AstNode *wire_node, uint32_t val = 1) @@ -535,8 +584,8 @@ ? wire_node->attributes[UhdmAst::unpacked_ranges()]->children : std::vector<AST::AstNode *>(); if (packed_ranges.empty() && unpacked_ranges.empty()) { - wire_node->attributes.erase(UhdmAst::packed_ranges()); - wire_node->attributes.erase(UhdmAst::unpacked_ranges()); + delete_attribute(wire_node, UhdmAst::packed_ranges()); + delete_attribute(wire_node, UhdmAst::unpacked_ranges()); wire_node->range_left = 0; wire_node->range_right = 0; wire_node->range_valid = true; @@ -600,8 +649,8 @@ } if (wire_node->type == AST::AST_STRUCT_ITEM || wire_node->type == AST::AST_STRUCT) { - wire_node->attributes.erase(UhdmAst::packed_ranges()); - wire_node->attributes.erase(UhdmAst::unpacked_ranges()); + delete_attribute(wire_node, UhdmAst::packed_ranges()); + delete_attribute(wire_node, UhdmAst::unpacked_ranges()); } // Insert new range @@ -657,10 +706,9 @@ } if (sub_dot) { // First select correct element in first struct - delete left; - delete right; - left = sub_dot->children[0]; - right = sub_dot->children[1]; + std::swap(left, sub_dot->children[0]); + std::swap(right, sub_dot->children[1]); + delete sub_dot; } if (struct_range) { // now we have correct element set, @@ -673,7 +721,7 @@ auto range_size = new AST::AstNode( AST::AST_ADD, new AST::AstNode(AST::AST_SUB, struct_range->children[0]->clone(), struct_range->children[1]->clone()), AST::AstNode::mkconst_int(1, true)); - right = new AST::AstNode(AST::AST_ADD, right->clone(), struct_range->children[1]->clone()); + right = new AST::AstNode(AST::AST_ADD, right, struct_range->children[1]->clone()); left = new AST::AstNode( AST::AST_ADD, left, new AST::AstNode(AST::AST_ADD, struct_range->children[1]->clone(), new AST::AstNode(AST::AST_SUB, range_size, elem_size->clone()))); @@ -715,6 +763,7 @@ "Accessing member of a slice of type %s is unsupported.\n", type2str(current_struct_elem->type).c_str()); } } + delete elem_size; // Return range from the begining of *current* struct // When all AST_DOT are expanded it will return range // from original wire @@ -840,6 +889,7 @@ snode->multirange_dimensions.push_back(min(range->range_left, range->range_right)); snode->multirange_dimensions.push_back(max(range->range_left, range->range_right) - min(range->range_left, range->range_right) + 1); snode->multirange_swapped.push_back(range->range_swapped); + delete range; } } // examine members from last to first @@ -1039,10 +1089,13 @@ dot = (dot_it != dot->children.end()) ? *dot_it : nullptr; } } - current_node->delete_children(); + delete_children(current_node); if (prefix_node != nullptr) { current_node->type = AST::AST_PREFIX; current_node->children = prefix_node->children; + + prefix_node->children.clear(); + delete prefix_node; } } else { auto wire_node = AST_INTERNAL::current_scope[current_node->str]; @@ -1052,12 +1105,10 @@ } } if (expanded) { - for (size_t i = 0; i < current_node->children.size(); i++) { - delete current_node->children[i]; - } - current_node->children.clear(); + delete_children(current_node); current_node->children.push_back(expanded->clone()); current_node->basic_prep = true; + delete expanded; expanded = nullptr; } // First simplify children @@ -1071,6 +1122,7 @@ AST_INTERNAL::current_scope[current_node->str] = current_node; break; case AST::AST_WIRE: + delete_attribute(current_node, UhdmAst::is_simplified_wire()); current_node->attributes[UhdmAst::is_simplified_wire()] = AST::AstNode::mkconst_int(1, true); [[fallthrough]]; case AST::AST_PARAMETER: @@ -1090,19 +1142,14 @@ if (!wire_node->attributes.count(UhdmAst::is_simplified_wire())) { simplify(wire_node, nullptr); } - const std::vector<AST::AstNode *> packed_ranges = wire_node->attributes.count(UhdmAst::packed_ranges()) - ? wire_node->attributes[UhdmAst::packed_ranges()]->children - : std::vector<AST::AstNode *>(); - const std::vector<AST::AstNode *> unpacked_ranges = wire_node->attributes.count(UhdmAst::unpacked_ranges()) - ? wire_node->attributes[UhdmAst::unpacked_ranges()]->children - : std::vector<AST::AstNode *>(); + const int packed_ranges_size = + wire_node->attributes.count(UhdmAst::packed_ranges()) ? wire_node->attributes[UhdmAst::packed_ranges()]->children.size() : 0; + const int unpacked_ranges_size = + wire_node->attributes.count(UhdmAst::unpacked_ranges()) ? wire_node->attributes[UhdmAst::unpacked_ranges()]->children.size() : 0; if ((wire_node->type == AST::AST_WIRE || wire_node->type == AST::AST_PARAMETER || wire_node->type == AST::AST_LOCALPARAM) && - !(packed_ranges.empty() && unpacked_ranges.empty()) && !(packed_ranges.size() + unpacked_ranges.size() == 1)) { - auto result = convert_range(current_node, packed_ranges, unpacked_ranges, 0); - for (size_t i = 0; i < current_node->children.size(); i++) { - delete current_node->children[i]; - } - current_node->children.clear(); + (packed_ranges_size + unpacked_ranges_size > 1)) { + auto *result = convert_range(current_node, packed_ranges_size, unpacked_ranges_size, 0); + delete_children(current_node); current_node->children.push_back(result); } } @@ -1146,7 +1193,10 @@ // save pointer that will be added later again // as conditions needs to go before this block auto result = current_node->children[1]; - current_node->children.clear(); + + current_node->children[0] = nullptr; + current_node->children[1] = nullptr; + delete_children(current_node); while (low_high_bound->children[0]->simplify(true, false, false, 1, -1, false, false)) { }; while (low_high_bound->children[1]->simplify(true, false, false, 1, -1, false, false)) { @@ -1166,7 +1216,7 @@ current_node->children.push_back(AST::AstNode::mkconst_int(i, false, range)); } current_node->children.push_back(result); - current_node->attributes.erase(UhdmAst::low_high_bound()); + delete_attribute(current_node, UhdmAst::low_high_bound()); } break; default: @@ -1326,6 +1376,7 @@ node->attributes[UhdmAst::packed_ranges()]->children[0]->children.size()) { size = node->attributes[UhdmAst::packed_ranges()]->children[0]->children[0]->integer + 1; } + delete node; }); if (size == -1) { size = vpi_get(vpiSize, obj_h); @@ -1566,15 +1617,18 @@ } else if (node) { current_node->str = node->str; if (node->type == AST::AST_ENUM && !node->children.empty()) { - for (auto c : node->children[0]->children) { + for (auto *c : node->children[0]->children) { if (c->type == AST::AST_RANGE && c->str.empty()) - packed_ranges.push_back(c->clone()); + packed_ranges.push_back(c); + else + delete c; } + node->children[0]->children.clear(); } delete node; } }); - add_multirange_wire(current_node, packed_ranges, unpacked_ranges); + add_multirange_wire(current_node, std::move(packed_ranges), std::move(unpacked_ranges)); } static void add_or_replace_child(AST::AstNode *parent, AST::AstNode *child) @@ -1604,12 +1658,16 @@ if ((*it)->attributes.count(UhdmAst::packed_ranges()) && child->attributes.count(UhdmAst::packed_ranges())) { if ((!(*it)->attributes[UhdmAst::packed_ranges()]->children.empty() && child->attributes[UhdmAst::packed_ranges()]->children.empty())) { + + delete_attribute(child, UhdmAst::packed_ranges()); child->attributes[UhdmAst::packed_ranges()] = (*it)->attributes[UhdmAst::packed_ranges()]->clone(); } } if ((*it)->attributes.count(UhdmAst::unpacked_ranges()) && child->attributes.count(UhdmAst::unpacked_ranges())) { if ((!(*it)->attributes[UhdmAst::unpacked_ranges()]->children.empty() && child->attributes[UhdmAst::unpacked_ranges()]->children.empty())) { + + delete_attribute(child, UhdmAst::unpacked_ranges()); child->attributes[UhdmAst::unpacked_ranges()] = (*it)->attributes[UhdmAst::unpacked_ranges()]->clone(); } } @@ -1654,6 +1712,7 @@ for (auto initial_child = child->children.begin() + 1; initial_child != child->children.end(); ++initial_child) { initial_node->children.push_back((*initial_child)->clone()); } + delete child; } else { // Parent AST_INITIAL does not exist // Place child AST_INITIAL before AST_ALWAYS if found @@ -1821,17 +1880,6 @@ pair.second = nullptr; } } - if (!shared.debug_flag) { - // Ranges were already converted, erase obsolete attributes - visitEachDescendant(current_node, [&](AST::AstNode *node) { - node->attributes.erase(UhdmAst::packed_ranges()); - node->attributes.erase(UhdmAst::unpacked_ranges()); - if (node->attributes.count(UhdmAst::is_simplified_wire())) { - delete node->attributes[UhdmAst::is_simplified_wire()]; - node->attributes.erase(UhdmAst::is_simplified_wire()); - } - }); - } } void UhdmAst::simplify_parameter(AST::AstNode *parameter, AST::AstNode *module_node) @@ -1891,11 +1939,7 @@ }); current_node->children.insert(current_node->children.end(), children_after_process.begin(), children_after_process.end()); - auto it = current_node->attributes.find(UhdmAst::partial()); - if (it != current_node->attributes.end()) { - delete it->second; - current_node->attributes.erase(it); - } + delete_attribute(current_node, UhdmAst::partial()); } else { current_node = make_ast_node(AST::AST_MODULE); current_node->str = type; @@ -1909,8 +1953,10 @@ }); visit_one_to_many({vpiModule, vpiParameter, vpiParamAssign, vpiNet, vpiArrayNet, vpiProcess}, obj_h, [&](AST::AstNode *node) { if (node) { - if (node->type == AST::AST_ASSIGN && node->children.size() < 2) + if (node->type == AST::AST_ASSIGN && node->children.size() < 2) { + delete node; return; + } add_or_replace_child(current_node, node); } }); @@ -1931,8 +1977,8 @@ } log_assert(node->children[0]->type == AST::AST_CONSTANT || node->children[0]->type == AST::AST_REALVALUE); parameters.push_back(std::make_pair(node->str, node->children[0]->asParaConst())); - delete node; } + delete node; }); // We need to rename module to prevent name collision with the same module, but with different parameters std::string module_name = !parameters.empty() ? AST::derived_module_name(type, parameters).c_str() : type; @@ -1979,8 +2025,7 @@ AST::AstNode *attr = module_node->attributes.at(UhdmAst::partial()); if (attr->type == AST::AST_CONSTANT) if (attr->integer == 1) { - delete attr; - module_node->attributes.erase(UhdmAst::partial()); + delete_attribute(module_node, UhdmAst::partial()); } } auto typeNode = new AST::AstNode(AST::AST_CELLTYPE); @@ -2008,13 +2053,14 @@ log_assert(!node->children[0]->children.empty()); log_assert(!node->children[0]->children[0]->children.empty()); // TODO: add missing enum_type attribute - auto range = make_range(0, 0); + AST::AstNode *range = nullptr; // check if single enum element is larger than 1 bit if (node->children[0]->children[0]->children.size() == 2) { range = node->children[0]->children[0]->children[1]->clone(); + } else { + range = make_range(0, 0); } - delete node->children[0]; - node->children.clear(); + delete_children(node); node->children.push_back(range); } current_node->children.push_back(node); @@ -2030,13 +2076,14 @@ log_assert(!node->children[0]->children.empty()); log_assert(!node->children[0]->children[0]->children.empty()); // TODO: add missing enum_type attribute - auto range = make_range(0, 0); + AST::AstNode *range = nullptr; // check if single enum element is larger than 1 bit if (node->children[0]->children[0]->children.size() == 2) { range = node->children[0]->children[0]->children[1]->clone(); + } else { + range = make_range(0, 0); } - delete node->children[0]; - node->children.clear(); + delete_children(node); node->children.push_back(range); } current_node->children.push_back(node); @@ -2134,13 +2181,13 @@ packed_ranges.push_back(r->clone()); } std::reverse(packed_ranges.begin(), packed_ranges.end()); - node->attributes.erase(UhdmAst::packed_ranges()); + delete_attribute(node, UhdmAst::packed_ranges()); } if (node->attributes.count(UhdmAst::unpacked_ranges())) { for (auto r : node->attributes[UhdmAst::unpacked_ranges()]->children) { unpacked_ranges.push_back(r->clone()); } - node->attributes.erase(UhdmAst::unpacked_ranges()); + delete_attribute(node, UhdmAst::unpacked_ranges()); } node->cloneInto(current_node); current_node->str = str; @@ -2154,13 +2201,13 @@ packed_ranges.push_back(r->clone()); } std::reverse(packed_ranges.begin(), packed_ranges.end()); - node->attributes.erase(UhdmAst::packed_ranges()); + delete_attribute(node, UhdmAst::packed_ranges()); } if (node->attributes.count(UhdmAst::unpacked_ranges())) { for (auto r : node->attributes[UhdmAst::unpacked_ranges()]->children) { unpacked_ranges.push_back(r->clone()); } - node->attributes.erase(UhdmAst::unpacked_ranges()); + delete_attribute(node, UhdmAst::unpacked_ranges()); } node->cloneInto(current_node); current_node->str = str; @@ -2452,12 +2499,12 @@ current_node->children.push_back(c->clone()); } } + delete_children(node); copy_packed_unpacked_attribute(node, current_node); - if (node->attributes.count(UhdmAst::is_imported())) { - current_node->attributes[UhdmAst::is_imported()] = node->attributes[UhdmAst::is_imported()]->clone(); - } current_node->is_custom_type = node->is_custom_type; - shared.param_types[current_node->str] = shared.param_types[node->str]; + auto it = shared.param_types.find(current_node->str); + if (it == shared.param_types.end()) + shared.param_types[current_node->str] = shared.param_types[node->str]; delete node; } }); @@ -2484,6 +2531,7 @@ if (node->type == AST::AST_WIRE || node->type == AST::AST_PARAMETER || node->type == AST::AST_LOCALPARAM) { assign_node->children.push_back(new AST::AstNode(AST::AST_IDENTIFIER)); assign_node->children.back()->str = node->str; + delete node; } else { assign_node->children.push_back(node); } @@ -2501,8 +2549,9 @@ current_node->children.push_back(new AST::AstNode(AST::AST_IDENTIFIER)); current_node->children.back()->str = node->str; } else { - current_node->children.push_back(node); + current_node->children.push_back(node->clone()); } + delete node; } }); } @@ -2617,8 +2666,9 @@ current_node = make_ast_node(AST::AST_WIRE); visit_one_to_many({vpiElement}, obj_h, [&](AST::AstNode *node) { if (node && GetSize(node->children) == 1) - current_node->children.push_back(node->children[0]); + current_node->children.push_back(node->children[0]->clone()); current_node->is_custom_type = node->is_custom_type; + delete node; }); visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); }); add_multirange_wire(current_node, packed_ranges, unpacked_ranges); @@ -2893,12 +2943,15 @@ if (node) { if ((node->type == AST::AST_ASSIGN_EQ || node->type == AST::AST_ASSIGN_LE) && node->children.size() == 1) { auto func_node = find_ancestor({AST::AST_FUNCTION, AST::AST_TASK}); - if (!func_node) + if (!func_node) { + delete node; return; + } auto wire_node = new AST::AstNode(AST::AST_WIRE); wire_node->type = AST::AST_WIRE; wire_node->str = node->children[0]->str; func_node->children.push_back(wire_node); + delete node; } else { if (hierarchy_node) hierarchy_node->children.push_back(node); @@ -3357,6 +3410,7 @@ std::find_if(param_type->children.begin(), param_type->children.end(), [key](AST::AstNode *child) { return child->str == key; }) - param_type->children.begin(); ordered_children.insert(std::make_pair(pos, node->children[1]->clone())); + delete node; } else { current_node->children.push_back(node); } @@ -3693,8 +3747,8 @@ for (auto c : node->children) { if (assign_types.find(c->type) != assign_types.end() && c->children[0]->type == AST::AST_WIRE) { c->children[0]->type = AST::AST_IDENTIFIER; - c->children[0]->attributes.erase(UhdmAst::packed_ranges()); - c->children[0]->attributes.erase(UhdmAst::unpacked_ranges()); + delete_attribute(c->children[0], UhdmAst::packed_ranges()); + delete_attribute(c->children[0], UhdmAst::unpacked_ranges()); } } current_node->children.push_back(node); @@ -3715,12 +3769,15 @@ if (!top_node) { current_node->str += node->str.substr(1); current_node->children = std::move(node->children); + node->children.clear(); top_node = current_node; delete node; } else { if (node->str.empty()) { log_assert(!node->children.empty()); top_node->children.push_back(node->children[0]); + node->children.erase(node->children.begin()); + delete node; } else { node->type = static_cast<AST::AstNodeType>(AST::Extended::AST_DOT); top_node->children.push_back(node); @@ -3770,7 +3827,7 @@ AST::AstNode *lhs_node = nullptr; if (assign_node) { assign_type = assign_node->type; - lhs_node = assign_node->children[0]; + lhs_node = assign_node->children[0]->clone(); } else { lhs_node = new AST::AstNode(AST::AST_IDENTIFIER); auto ancestor = find_ancestor({AST::AST_WIRE, AST::AST_MEMORY, AST::AST_PARAMETER, AST::AST_LOCALPARAM}); @@ -3780,7 +3837,7 @@ lhs_node->str = ancestor->str; } current_node = new AST::AstNode(assign_type); - current_node->children.push_back(lhs_node->clone()); + current_node->children.push_back(lhs_node); auto typespec_h = vpi_handle(vpiTypespec, obj_h); if (vpi_get(vpiType, typespec_h) == vpiStringTypespec) { std::string field_name = vpi_get_str(vpiName, typespec_h); @@ -4121,11 +4178,12 @@ case vpiPackedArrayVar: visit_one_to_many({vpiElement}, actual_h, [&](AST::AstNode *node) { if (node && GetSize(node->children) == 1) { - current_node->children.push_back(node->children[0]); + current_node->children.push_back(node->children[0]->clone()); if (node->children[0]->type == AST::AST_WIRETYPE) { current_node->is_custom_type = true; } } + delete node; }); visit_one_to_many({vpiRange}, actual_h, [&](AST::AstNode *node) { current_node->children.push_back(node); }); shared.report.mark_handled(actual_h); @@ -4212,6 +4270,7 @@ current_node->children.insert(current_node->children.begin(), wiretype_node); current_node->is_custom_type = true; } + delete node; }); if (vpiHandle typespec_h = vpi_handle(vpiTypespec, obj_h)) { visit_one_to_many({vpiRange}, typespec_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); }); @@ -4226,10 +4285,6 @@ current_node = make_ast_node(type, {}, true); std::vector<AST::AstNode *> packed_ranges; // comes before wire name std::vector<AST::AstNode *> unpacked_ranges; // comes after wire name - // currently unused, but save it for future use - if (const char *imported = vpi_get_str(vpiImported, obj_h); imported != nullptr && strlen(imported) > 0) { - current_node->attributes[UhdmAst::is_imported()] = AST::AstNode::mkconst_int(1, true); - } visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { unpacked_ranges.push_back(node); }); vpiHandle typespec_h = vpi_handle(vpiTypespec, obj_h); if (typespec_h) { @@ -4282,8 +4337,11 @@ } current_node->is_custom_type = true; auto it = shared.param_types.find(current_node->str); - if (it == shared.param_types.end()) + if (it == shared.param_types.end()) { shared.param_types.insert(std::make_pair(current_node->str, node)); + } else { + delete node; + } }); break; } @@ -4298,13 +4356,14 @@ current_node->is_custom_type = true; auto it = shared.param_types.find(current_node->str); if (it == shared.param_types.end()) - shared.param_types.insert(std::make_pair(current_node->str, node)); + shared.param_types.insert(std::make_pair(current_node->str, node->clone())); } if (node && node->attributes.count(UhdmAst::packed_ranges())) { for (auto r : node->attributes[UhdmAst::packed_ranges()]->children) { packed_ranges.push_back(r->clone()); } } + delete node; }); break; } @@ -4733,13 +4792,20 @@ current_node = new AST::AstNode(AST::AST_DESIGN); for (auto design : designs) { UhdmAst ast(this, shared, indent); - auto *nodes = ast.process_object(design); + auto *processed_design_node = ast.process_object(design); // Flatten multiple designs into one - for (auto child : nodes->children) { - current_node->children.push_back(child); - } + current_node->children = std::move(processed_design_node->children); + delete processed_design_node; } + for (auto &[name, node] : shared.param_types) { + delete node; + } + shared.param_types.clear(); + + // Remove all internal attributes from the AST. + visitEachDescendant(current_node, delete_internal_attributes); + attr_id_cleanup(); return current_node;
diff --git a/systemverilog-plugin/uhdmastshared.h b/systemverilog-plugin/uhdmastshared.h index 475ba70..36a1068 100644 --- a/systemverilog-plugin/uhdmastshared.h +++ b/systemverilog-plugin/uhdmastshared.h
@@ -21,6 +21,13 @@ unsigned loop_count = 0; public: + ~UhdmAstShared() + { + for (const auto ¶m : param_types) + delete param.second; + param_types.clear(); + } + // Generate the next enum ID (starting with 0) unsigned next_enum_id() { return enum_count++; }