diff options
author | Clifford Wolf <clifford@clifford.at> | 2016-05-27 17:25:33 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2016-05-27 17:25:33 +0200 |
commit | ee071586c55915c6535bad0a47bf80c8f2029272 (patch) | |
tree | 6c48a5aa9b57bbf58d03480240eac5bc40024d42 /frontends | |
parent | e9ceec26ffe773d36b5316c79149913777d6581f (diff) | |
download | yosys-ee071586c55915c6535bad0a47bf80c8f2029272.tar.gz yosys-ee071586c55915c6535bad0a47bf80c8f2029272.tar.bz2 yosys-ee071586c55915c6535bad0a47bf80c8f2029272.zip |
Fixed access-after-delete bug in mem2reg code
Diffstat (limited to 'frontends')
-rw-r--r-- | frontends/ast/ast.h | 1 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 28 |
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) { |