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++; }