aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/ast
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2016-05-27 17:25:33 +0200
committerClifford Wolf <clifford@clifford.at>2016-05-27 17:25:33 +0200
commitee071586c55915c6535bad0a47bf80c8f2029272 (patch)
tree6c48a5aa9b57bbf58d03480240eac5bc40024d42 /frontends/ast
parente9ceec26ffe773d36b5316c79149913777d6581f (diff)
downloadyosys-ee071586c55915c6535bad0a47bf80c8f2029272.tar.gz
yosys-ee071586c55915c6535bad0a47bf80c8f2029272.tar.bz2
yosys-ee071586c55915c6535bad0a47bf80c8f2029272.zip
Fixed access-after-delete bug in mem2reg code
Diffstat (limited to 'frontends/ast')
-rw-r--r--frontends/ast/ast.h1
-rw-r--r--frontends/ast/simplify.cc28
2 files changed, 23 insertions, 6 deletions
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index b4e58d79f..21c3ba3c6 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -219,6 +219,7 @@ namespace AST
dict<AstNode*, uint32_t> &mem2reg_flags, dict<AstNode*, uint32_t> &proc_flags, uint32_t &status_flags);
bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block);
bool mem2reg_check(pool<AstNode*> &mem2reg_set);
+ void mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes);
void meminfo(int &mem_width, int &mem_size, int &addr_bits);
// additional functionality for evaluating constant functions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index e00087280..c09b912c2 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -150,12 +150,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (mem2reg_as_needed_pass2(mem2reg_set, this, NULL)) { }
- for (size_t i = 0; i < children.size(); i++) {
- if (mem2reg_set.count(children[i]) > 0) {
- delete children[i];
- children.erase(children.begin() + (i--));
- }
- }
+ vector<AstNode*> delnodes;
+ mem2reg_remove(mem2reg_set, delnodes);
+
+ for (auto node : delnodes)
+ delete node;
}
while (simplify(const_fold, at_zero, in_lvalue, 2, width_hint, sign_hint, in_param)) { }
@@ -2606,6 +2605,23 @@ bool AstNode::mem2reg_check(pool<AstNode*> &mem2reg_set)
return true;
}
+void AstNode::mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes)
+{
+ log_assert(mem2reg_set.count(this) == 0);
+
+ if (mem2reg_set.count(id2ast))
+ id2ast = nullptr;
+
+ for (size_t i = 0; i < children.size(); i++) {
+ if (mem2reg_set.count(children[i]) > 0) {
+ delnodes.push_back(children[i]);
+ children.erase(children.begin() + (i--));
+ } else {
+ children[i]->mem2reg_remove(mem2reg_set, delnodes);
+ }
+ }
+}
+
// actually replace memories with registers
bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block)
{