From 73122921f5427f7b770d78bf8f04953f175de453 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 21 May 2025 12:14:50 +0200 Subject: [PATCH] ast, read_verilog: ownership in AST, use C++ styles for parser and lexer --- Makefile | 2 +- flake.nix | 2 +- frontends/ast/ast.cc | 340 ++-- frontends/ast/ast.h | 59 +- frontends/ast/dpicall.cc | 8 +- frontends/ast/genrtlil.cc | 206 +-- frontends/ast/simplify.cc | 1420 +++++++-------- frontends/verilog/.gitignore | 3 + frontends/verilog/Makefile.inc | 1 + frontends/verilog/const2ast.cc | 10 +- frontends/verilog/verilog_frontend.cc | 53 +- frontends/verilog/verilog_frontend.h | 49 +- frontends/verilog/verilog_lexer.l | 538 +++--- frontends/verilog/verilog_parser.y | 2390 ++++++++++++------------- kernel/rtlil.cc | 12 +- kernel/rtlil.h | 2 +- passes/cmds/design.cc | 6 - passes/memory/memlib.h | 2 +- tests/sat/alu.v | 2 +- tests/various/svalways.sh | 2 +- tests/verilog/bug2042-sv.ys | 2 +- tests/verilog/task_attr.ys | 2 +- 22 files changed, 2496 insertions(+), 2615 deletions(-) diff --git a/Makefile b/Makefile index 74857d3a8..901ea48c8 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,7 @@ endif PKG_CONFIG ?= pkg-config SED ?= sed -BISON ?= bison +BISON ?= bison -k STRIP ?= strip AWK ?= awk diff --git a/flake.nix b/flake.nix index 19ba59f17..00ad7d865 100644 --- a/flake.nix +++ b/flake.nix @@ -41,7 +41,7 @@ packages.default = yosys; defaultPackage = yosys; devShell = pkgs.mkShell { - buildInputs = with pkgs; [ clang llvmPackages.bintools gcc bison flex libffi tcl readline python3 zlib git gtest abc-verifier verilog boost python3Packages.boost ]; + buildInputs = with pkgs; [ clang llvmPackages.bintools gcc bison flex libffi tcl readline python3 zlib git gtest abc-verifier verilog boost python3Packages.boost valgrind ]; }; } ); diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 431f7b4f8..d87e5fc6b 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -39,8 +39,6 @@ using namespace AST_INTERNAL; // instantiate global variables (public API) namespace AST { std::string current_filename; - void (*set_line_num)(int) = NULL; - int (*get_line_num)() = NULL; unsigned long long astnodes = 0; unsigned long long astnode_count() { return astnodes; } } @@ -192,16 +190,16 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id) if (attributes.count(id) == 0) return false; - AstNode *attr = attributes.at(id); - if (attr->type != AST_CONSTANT) - attr->input_error("Attribute `%s' with non-constant value!\n", id.c_str()); + AstNode& attr = *(attributes.at(id)); + if (attr.type != AST_CONSTANT) + attr.input_error("Attribute `%s' with non-constant value!\n", id.c_str()); - return attr->integer != 0; + return attr.integer != 0; } // create new node (AstNode constructor) // (the optional child arguments make it easier to create AST trees) -AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *child3, AstNode *child4) +AstNode::AstNode(AstNodeType type, std::unique_ptr child1, std::unique_ptr child2, std::unique_ptr child3, std::unique_ptr child4) { static unsigned int hashidx_count = 123456789; hashidx_count = mkhash_xorshift(hashidx_count); @@ -239,56 +237,74 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch in_param = false; if (child1) - children.push_back(child1); + children.push_back(std::move(child1)); if (child2) - children.push_back(child2); + children.push_back(std::move(child2)); if (child3) - children.push_back(child3); + children.push_back(std::move(child3)); if (child4) - children.push_back(child4); + children.push_back(std::move(child4)); fixup_hierarchy_flags(); } // create a (deep recursive) copy of a node -AstNode *AstNode::clone() const +std::unique_ptr AstNode::clone() const { - AstNode *that = new AstNode; - *that = *this; - for (auto &it : that->children) - it = it->clone(); - for (auto &it : that->attributes) - it.second = it.second->clone(); - - that->set_in_lvalue_flag(false); - that->set_in_param_flag(false); - that->fixup_hierarchy_flags(); // fixup to set flags on cloned children + auto that = std::make_unique(this->type); + cloneInto(*that.get()); return that; } // create a (deep recursive) copy of a node use 'other' as target root node -void AstNode::cloneInto(AstNode *other) const +void AstNode::cloneInto(AstNode &other) const { - AstNode *tmp = clone(); - tmp->in_lvalue_from_above = other->in_lvalue_from_above; - tmp->in_param_from_above = other->in_param_from_above; - other->delete_children(); - *other = *tmp; - tmp->children.clear(); - tmp->attributes.clear(); - other->fixup_hierarchy_flags(); - delete tmp; + other.type = type; + other.str = str; + other.bits = bits; + other.is_input = is_input; + other.is_output = is_output; + other.is_reg = is_reg; + other.is_logic = is_logic; + other.is_signed = is_signed; + other.is_string = is_string; + other.is_wand = is_wand; + other.is_wor = is_wor; + other.range_valid = range_valid; + other.range_swapped = range_swapped; + other.was_checked = was_checked; + other.is_unsized = is_unsized; + other.is_custom_type = is_custom_type; + other.port_id = port_id, + other.range_left = range_left, + other.range_right = range_right; + other.integer = integer; + other.realvalue = realvalue; + other.is_enum = is_enum; + other.dimensions = dimensions; + other.unpacked_dimensions = unpacked_dimensions; + other.id2ast = id2ast; + other.basic_prep = basic_prep; + other.lookahead = lookahead; + other.filename = filename; + other.location = location; + other.in_lvalue = in_lvalue; + other.in_param = in_param; + // Keep in_lvalue_from_above and in_param_from_above untouched + + other.delete_children(); + for (auto& child : this->children) + other.children.push_back(child->clone()); + for (auto& [key, val] : this->attributes) + other.attributes[key] = (val->clone()); + // fixup to set flags on cloned children + other.fixup_hierarchy_flags(); } // delete all children in this node void AstNode::delete_children() { - for (auto &it : children) - delete it; children.clear(); - - for (auto &it : attributes) - delete it.second; attributes.clear(); } @@ -423,18 +439,18 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const { case AST_MODULE: fprintf(f, "%s" "module %s(", indent.c_str(), id2vl(str).c_str()); - for (auto child : children) + for (const auto& child : children) if (child->type == AST_WIRE && (child->is_input || child->is_output)) { fprintf(f, "%s%s", first ? "" : ", ", id2vl(child->str).c_str()); first = false; } fprintf(f, ");\n"); - for (auto child : children) + for (const auto& child : children) if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_DEFPARAM) child->dumpVlog(f, indent + " "); else - rem_children1.push_back(child); + rem_children1.push_back(child.get()); for (auto child : rem_children1) if (child->type == AST_WIRE || child->type == AST_AUTOWIRE || child->type == AST_MEMORY) @@ -470,7 +486,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const fprintf(f, "%s" "reg", (is_input || is_output) ? " " : indent.c_str()); if (is_signed) fprintf(f, " signed"); - for (auto child : children) { + for (const auto& child : children) { fprintf(f, " "); child->dumpVlog(f, ""); } @@ -486,7 +502,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const fprintf(f, "%s" "memory", indent.c_str()); if (is_signed) fprintf(f, " signed"); - for (auto child : children) { + for (const auto& child : children) { fprintf(f, " "); child->dumpVlog(f, ""); if (first) @@ -500,7 +516,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const if (0) { case AST_MEMINIT: txt = "@meminit@"; } if (0) { case AST_MEMWR: txt = "@memwr@"; } fprintf(f, "%s%s", indent.c_str(), txt.c_str()); - for (auto child : children) { + for (const auto& child : children) { fprintf(f, first ? "(" : ", "); child->dumpVlog(f, ""); first = false; @@ -517,7 +533,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const else fprintf(f, "[%d:%d]", range_left, range_right); } else { - for (auto child : children) { + for (const auto& child : children) { fprintf(f, "%c", first ? '[' : ':'); child->dumpVlog(f, ""); first = false; @@ -527,13 +543,13 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const break; case AST_MULTIRANGE: - for (auto child : children) + for (const auto& child : children) child->dumpVlog(f, ""); break; case AST_ALWAYS: fprintf(f, "%s" "always @", indent.c_str()); - for (auto child : children) { + for (const auto& child : children) { if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE) continue; fprintf(f, first ? "(" : ", "); @@ -541,7 +557,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const first = false; } fprintf(f, first ? "*\n" : ")\n"); - for (auto child : children) { + for (const auto& child : children) { if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE) child->dumpVlog(f, indent + " "); } @@ -549,7 +565,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const case AST_INITIAL: fprintf(f, "%s" "initial\n", indent.c_str()); - for (auto child : children) { + for (const auto& child : children) { if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE) child->dumpVlog(f, indent + " "); } @@ -562,7 +578,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const fprintf(f, "posedge "); if (type == AST_NEGEDGE) fprintf(f, "negedge "); - for (auto child : children) + for (const auto& child : children) child->dumpVlog(f, ""); break; @@ -574,7 +590,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const else fprintf(f, "%s", id2vl(str).c_str()); } - for (auto child : children) + for (const auto& child : children) child->dumpVlog(f, ""); break; @@ -602,7 +618,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const children[0]->dumpVlog(f, indent); } else { fprintf(f, "%s" "begin\n", indent.c_str()); - for (auto child : children) + for (const auto& child : children) child->dumpVlog(f, indent + " "); fprintf(f, "%s" "end\n", indent.c_str()); } @@ -618,7 +634,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const children[0]->dumpVlog(f, ""); fprintf(f, ")\n"); for (size_t i = 1; i < children.size(); i++) { - AstNode *child = children[i]; + const auto& child = children[i]; child->dumpVlog(f, indent + " "); } fprintf(f, "%s" "endcase\n", indent.c_str()); @@ -627,7 +643,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const case AST_COND: case AST_CONDX: case AST_CONDZ: - for (auto child : children) { + for (const auto& child : children) { if (child->type == AST_BLOCK) { fprintf(f, ":\n"); child->dumpVlog(f, indent + " "); @@ -663,7 +679,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const case AST_CONCAT: fprintf(f, "{"); for (int i = GetSize(children)-1; i >= 0; i--) { - auto child = children[i]; + const auto& child = children[i]; if (!first) fprintf(f, ", "); child->dumpVlog(f, ""); @@ -818,16 +834,16 @@ bool AstNode::contains(const AstNode *other) const { if (this == other) return true; - for (auto child : children) + for (const auto& child : children) if (child->contains(other)) return true; return false; } // create an AST node for a constant (using a 32 bit int as value) -AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width) +std::unique_ptr AstNode::mkconst_int(uint32_t v, bool is_signed, int width) { - AstNode *node = new AstNode(AST_CONSTANT); + auto node = std::make_unique(AST_CONSTANT); node->integer = v; node->is_signed = is_signed; for (int i = 0; i < width; i++) { @@ -841,9 +857,9 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width) } // create an AST node for a constant (using a bit vector as value) -AstNode *AstNode::mkconst_bits(const std::vector &v, bool is_signed, bool is_unsized) +std::unique_ptr AstNode::mkconst_bits(const std::vector &v, bool is_signed, bool is_unsized) { - AstNode *node = new AstNode(AST_CONSTANT); + auto node = std::make_unique(AST_CONSTANT); node->is_signed = is_signed; node->bits = v; for (size_t i = 0; i < 32; i++) { @@ -859,15 +875,15 @@ AstNode *AstNode::mkconst_bits(const std::vector &v, bool is_signe return node; } -AstNode *AstNode::mkconst_bits(const std::vector &v, bool is_signed) +std::unique_ptr AstNode::mkconst_bits(const std::vector &v, bool is_signed) { return mkconst_bits(v, is_signed, false); } // create an AST node for a constant (using a string in bit vector form as value) -AstNode *AstNode::mkconst_str(const std::vector &v) +std::unique_ptr AstNode::mkconst_str(const std::vector &v) { - AstNode *node = mkconst_str(RTLIL::Const(v).decode_string()); + auto node = mkconst_str(RTLIL::Const(v).decode_string()); while (GetSize(node->bits) < GetSize(v)) node->bits.push_back(RTLIL::State::S0); log_assert(node->bits == v); @@ -875,9 +891,9 @@ AstNode *AstNode::mkconst_str(const std::vector &v) } // create an AST node for a constant (using a string as value) -AstNode *AstNode::mkconst_str(const std::string &str) +std::unique_ptr AstNode::mkconst_str(const std::string &str) { - AstNode *node; + std::unique_ptr node; // LRM 1364-2005 5.2.3.3 The empty string literal ("") shall be considered // equivalent to the ASCII NUL ("\0") @@ -902,18 +918,19 @@ AstNode *AstNode::mkconst_str(const std::string &str) } // create a temporary register -AstNode *AstNode::mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed) +std::unique_ptr AstNode::mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed) { - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(range_left, true), mkconst_int(range_right, true))); + auto wire_owned = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(range_left, true), mkconst_int(range_right, true))); + auto* wire = wire_owned.get(); wire->str = stringf("%s%s:%d$%d", name.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++); if (nosync) wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); wire->is_signed = is_signed; wire->is_logic = true; - mod->children.push_back(wire); + mod->children.push_back(std::move(wire_owned)); while (wire->simplify(true, 1, -1, false)) { } - AstNode *ident = new AstNode(AST_IDENTIFIER); + auto ident = std::make_unique(AST_IDENTIFIER); ident->str = wire->str; ident->id2ast = wire; @@ -967,10 +984,9 @@ RTLIL::Const AstNode::asParaConst() const { if (type == AST_REALVALUE) { - AstNode *strnode = AstNode::mkconst_str(stringf("%f", realvalue)); + auto strnode = AstNode::mkconst_str(stringf("%f", realvalue)); RTLIL::Const val = strnode->asAttrConst(); val.flags |= RTLIL::CONST_FLAG_REAL; - delete strnode; return val; } @@ -1078,7 +1094,7 @@ void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast) obj->attributes[ID::src] = ast->loc_string(); } -static bool param_has_no_default(const AstNode *param) { +static bool param_has_no_default(const std::unique_ptr ¶m) { const auto &children = param->children; log_assert(param->type == AST_PARAMETER); log_assert(children.size() <= 2); @@ -1086,7 +1102,7 @@ static bool param_has_no_default(const AstNode *param) { (children.size() == 1 && children[0]->type == AST_RANGE); } -static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false) +static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool defer, std::unique_ptr original_ast = NULL, bool quiet = false) { log_assert(current_scope.empty()); log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE); @@ -1100,15 +1116,15 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d AstModule *module = new AstModule; current_module = module; - module->ast = NULL; + module->ast = nullptr; module->name = ast->str; set_src_attr(module, ast); module->set_bool_attribute(ID::cells_not_processed); current_ast_mod = ast; - AstNode *ast_before_simplify; + std::unique_ptr ast_before_simplify; if (original_ast != NULL) - ast_before_simplify = original_ast; + ast_before_simplify = std::move(original_ast); else ast_before_simplify = ast->clone(); @@ -1125,7 +1141,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d if (!defer) { - for (const AstNode *node : ast->children) + for (auto& node : ast->children) if (node->type == AST_PARAMETER && param_has_no_default(node)) node->input_error("Parameter `%s' has no default value and has not been overridden!\n", node->str.c_str()); @@ -1133,7 +1149,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d if (!blackbox_module && !flag_noblackbox) { blackbox_module = true; - for (auto child : ast->children) { + for (const auto& child : ast->children) { if (child->type == AST_WIRE && (child->is_input || child->is_output)) continue; if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM) @@ -1163,36 +1179,33 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d ast->dumpVlog(NULL, " "); log("--- END OF AST DUMP ---\n"); } - + for (auto &attr: ast->attributes) + log_assert((bool)attr.second.get()); if (flag_nowb && ast->attributes.count(ID::whitebox)) { - delete ast->attributes.at(ID::whitebox); ast->attributes.erase(ID::whitebox); } - + for (auto &attr: ast->attributes) + log_assert((bool)attr.second.get()); if (ast->attributes.count(ID::lib_whitebox)) { - if (!flag_lib || flag_nowb) { - delete ast->attributes.at(ID::lib_whitebox); - ast->attributes.erase(ID::lib_whitebox); - } else { - if (ast->attributes.count(ID::whitebox)) { - delete ast->attributes.at(ID::whitebox); - ast->attributes.erase(ID::whitebox); - } - AstNode *n = ast->attributes.at(ID::lib_whitebox); - ast->set_attribute(ID::whitebox, n); - ast->attributes.erase(ID::lib_whitebox); + if (flag_lib && !flag_nowb) { + ast->attributes[ID::whitebox] = std::move( + ast->attributes[ID::lib_whitebox] + ); } + ast->attributes.erase(ID::lib_whitebox); } + for (auto &attr: ast->attributes) + log_assert((bool)attr.second.get()); if (!blackbox_module && ast->attributes.count(ID::blackbox)) { - AstNode *n = ast->attributes.at(ID::blackbox); + auto& n = ast->attributes.at(ID::blackbox); if (n->type != AST_CONSTANT) ast->input_error("Got blackbox attribute with non-constant value!\n"); blackbox_module = n->asBool(); } if (blackbox_module && ast->attributes.count(ID::whitebox)) { - AstNode *n = ast->attributes.at(ID::whitebox); + auto& n = ast->attributes.at(ID::whitebox); if (n->type != AST_CONSTANT) ast->input_error("Got whitebox attribute with non-constant value!\n"); blackbox_module = !n->asBool(); @@ -1200,38 +1213,34 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d if (ast->attributes.count(ID::noblackbox)) { if (blackbox_module) { - AstNode *n = ast->attributes.at(ID::noblackbox); + auto& n = ast->attributes.at(ID::noblackbox); if (n->type != AST_CONSTANT) ast->input_error("Got noblackbox attribute with non-constant value!\n"); blackbox_module = !n->asBool(); } - delete ast->attributes.at(ID::noblackbox); ast->attributes.erase(ID::noblackbox); } - + for (auto &attr: ast->attributes) + log_assert((bool)attr.second.get()); if (blackbox_module) { if (ast->attributes.count(ID::whitebox)) { - delete ast->attributes.at(ID::whitebox); ast->attributes.erase(ID::whitebox); } if (ast->attributes.count(ID::lib_whitebox)) { - delete ast->attributes.at(ID::lib_whitebox); ast->attributes.erase(ID::lib_whitebox); } - std::vector new_children; - for (auto child : ast->children) { + std::vector> new_children; + for (auto& child : ast->children) { if (child->type == AST_WIRE && (child->is_input || child->is_output)) { - new_children.push_back(child); + new_children.push_back(std::move(child)); } else if (child->type == AST_PARAMETER) { - new_children.push_back(child); + new_children.push_back(std::move(child)); } else if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE && (child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule")) { - new_children.push_back(child); - } else { - delete child; + new_children.push_back(std::move(child)); } } @@ -1245,17 +1254,18 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d ignoreThisSignalsInInitial = RTLIL::SigSpec(); for (auto &attr : ast->attributes) { + log_assert((bool)attr.second.get()); if (attr.second->type != AST_CONSTANT) ast->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str()); module->attributes[attr.first] = attr.second->asAttrConst(); } for (size_t i = 0; i < ast->children.size(); i++) { - AstNode *node = ast->children[i]; + const auto& node = ast->children[i]; if (node->type == AST_WIRE || node->type == AST_MEMORY) node->genRTLIL(); } for (size_t i = 0; i < ast->children.size(); i++) { - AstNode *node = ast->children[i]; + const auto& node = ast->children[i]; if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL) node->genRTLIL(); } @@ -1263,7 +1273,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d ignoreThisSignalsInInitial.sort_and_unify(); for (size_t i = 0; i < ast->children.size(); i++) { - AstNode *node = ast->children[i]; + const auto& node = ast->children[i]; if (node->type == AST_INITIAL) node->genRTLIL(); } @@ -1277,14 +1287,14 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d continue; module->attributes[attr.first] = attr.second->asAttrConst(); } - for (const AstNode *node : ast->children) + for (const auto& node : ast->children) if (node->type == AST_PARAMETER) current_module->avail_parameters(node->str); } if (ast->type == AST_INTERFACE) module->set_bool_attribute(ID::is_interface); - module->ast = ast_before_simplify; + module->ast = std::move(ast_before_simplify); module->nolatches = flag_nolatches; module->nomeminit = flag_nomeminit; module->nomem2reg = flag_nomem2reg; @@ -1311,8 +1321,8 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d RTLIL::Module * AST_INTERNAL::process_and_replace_module(RTLIL::Design *design, RTLIL::Module *old_module, - AstNode *new_ast, - AstNode *original_ast) + AST::AstNode *new_ast, + std::unique_ptr original_ast) { // The old module will be deleted. Rename and mark for deletion, using // a static counter to make sure we get a unique name. @@ -1335,7 +1345,7 @@ AST_INTERNAL::process_and_replace_module(RTLIL::Design *design, } // Generate RTLIL from AST for the new module and add to the design: - RTLIL::Module* new_module = process_module(design, new_ast, false, original_ast); + RTLIL::Module* new_module = process_module(design, new_ast, false, std::move(original_ast)); if (is_top) new_module->set_bool_attribute(ID::top); @@ -1347,17 +1357,17 @@ AST_INTERNAL::process_and_replace_module(RTLIL::Design *design, static void rename_in_package_stmts(AstNode *pkg) { std::unordered_set idents; - for (AstNode *item : pkg->children) + for (auto& item : pkg->children) idents.insert(item->str); - std::function rename = - [&rename, &idents, pkg](AstNode *node) { - for (AstNode *child : node->children) { + std::function&)> rename = + [&rename, &idents, pkg](std::unique_ptr& node) { + for (auto& child : node->children) { if (idents.count(child->str)) child->str = pkg->str + "::" + child->str.substr(1); rename(child); } }; - for (AstNode *item : pkg->children) + for (auto& item : pkg->children) if (item->type == AST_FUNCTION || item->type == AST_TASK) rename(item); } @@ -1390,17 +1400,17 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump ast->fixup_hierarchy_flags(true); log_assert(current_ast->type == AST_DESIGN); - for (AstNode *child : current_ast->children) + for (const auto& child : current_ast->children) { if (child->type == AST_MODULE || child->type == AST_INTERFACE) { - for (auto n : design->verilog_globals) + for (auto& n : design->verilog_globals) child->children.push_back(n->clone()); // append nodes from previous packages using package-qualified names - for (auto &n : design->verilog_packages) { + for (auto& n : design->verilog_packages) { for (auto &o : n->children) { - AstNode *cloned_node = o->clone(); + auto cloned_node = o->clone(); // log("cloned node %s\n", type2str(cloned_node->type).c_str()); if (cloned_node->type == AST_ENUM) { for (auto &e : cloned_node->children) { @@ -1410,7 +1420,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump } else { cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1); } - child->children.push_back(cloned_node); + child->children.push_back(std::move(cloned_node)); } } @@ -1419,7 +1429,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump bool defer_local = defer; if (!defer_local) - for (const AstNode *node : child->children) + for (const auto& node : child->children) if (node->type == AST_PARAMETER && param_has_no_default(node)) { log("Deferring `%s' because it contains parameter(s) without defaults.\n", child->str.c_str()); @@ -1447,13 +1457,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump } } - process_module(design, child, defer_local); + process_module(design, child.get(), defer_local); current_ast_mod = nullptr; } else if (child->type == AST_PACKAGE) { // process enum/other declarations child->simplify(true, 1, -1, false); - rename_in_package_stmts(child); + rename_in_package_stmts(child.get()); design->verilog_packages.push_back(child->clone()); current_scope.clear(); } @@ -1472,14 +1482,6 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump } } -// AstModule destructor -AstModule::~AstModule() -{ - if (ast != NULL) - delete ast; -} - - // An interface port with modport is specified like this: // . // This function splits the interface_name from the modport_name, and fails if it is not a valid combination @@ -1516,7 +1518,7 @@ AstNode * AST::find_modport(AstNode *intf, std::string name) for (auto &ch : intf->children) if (ch->type == AST_MODPORT) if (ch->str == name) // Modport found - return ch; + return ch.get(); return NULL; } @@ -1524,7 +1526,7 @@ AstNode * AST::find_modport(AstNode *intf, std::string name) void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport) { for (auto w : intfmodule->wires()){ - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true))); + auto wire = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true))); std::string origname = log_id(w->name); std::string newname = intfname + "." + origname; wire->str = newname; @@ -1543,16 +1545,13 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule } } if (found_in_modport) { - module_ast->children.push_back(wire); - } - else { // If not found in modport, do not create port - delete wire; + module_ast->children.push_back(std::move(wire)); } } else { // If no modport, set inout wire->is_input = true; wire->is_output = true; - module_ast->children.push_back(wire); + module_ast->children.push_back(std::move(wire)); } } } @@ -1570,7 +1569,7 @@ bool AstModule::reprocess_if_necessary(RTLIL::Design *design) log("Reprocessing module %s because instantiated module %s has become available.\n", log_id(name), log_id(modname)); loadconfig(); - process_and_replace_module(design, this, ast, NULL); + process_and_replace_module(design, this, ast.get(), NULL); return true; } } @@ -1583,32 +1582,32 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dictclone(); + auto new_ast = ast->clone(); for (auto &intf : local_interfaces) { std::string intfname = intf.first.str(); RTLIL::Module *intfmodule = intf.second; for (auto w : intfmodule->wires()){ - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true))); + auto wire = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true))); std::string newname = log_id(w->name); newname = intfname + "." + newname; wire->str = newname; - new_ast->children.push_back(wire); + new_ast->children.push_back(std::move(wire)); } } - AstNode *ast_before_replacing_interface_ports = new_ast->clone(); + auto ast_before_replacing_interface_ports = new_ast->clone(); // Explode all interface ports. Note this will only have an effect on 'top // level' modules. Other sub-modules will have their interface ports // exploded via the derive(..) function for (size_t i =0; ichildren.size(); i++) { - AstNode *ch2 = new_ast->children[i]; + const auto& ch2 = new_ast->children[i]; if (ch2->type == AST_INTERFACEPORT) { // Is an interface port std::string name_port = ch2->str; // Name of the interface port if (ch2->children.size() > 0) { for(size_t j=0; jchildren.size();j++) { - AstNode *ch = ch2->children[j]; + const auto& ch = ch2->children[j]; if(ch->type == AST_INTERFACEPORTTYPE) { // Found the AST node containing the type of the interface std::pair res = split_modport_from_type(ch->str); std::string interface_type = res.first; @@ -1616,11 +1615,11 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dictmodule(interface_type) != nullptr) { // Add a cell to the module corresponding to the interface port such that // it can further propagated down if needed: - AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE); + auto celltype_for_intf = std::make_unique(AST_CELLTYPE); celltype_for_intf->str = interface_type; - AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf); + auto cell_for_intf = std::make_unique(AST_CELL, std::move(celltype_for_intf)); cell_for_intf->str = name_port + "_inst_from_top_dummy"; - new_ast->children.push_back(cell_for_intf); + new_ast->children.push_back(std::move(cell_for_intf)); // Get all members of this non-overridden dummy interface instance: RTLIL::Module *intfmodule = design->module(interface_type); // All interfaces should at this point in time (assuming @@ -1628,9 +1627,9 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dictmodules_ AstModule *ast_module_of_interface = (AstModule*)intfmodule; std::string interface_modport_compare_str = "\\" + interface_modport; - AstNode *modport = find_modport(ast_module_of_interface->ast, interface_modport_compare_str); // modport == NULL if no modport + AstNode *modport = find_modport(ast_module_of_interface->ast.get(), interface_modport_compare_str); // modport == NULL if no modport // Iterate over all wires in the interface and add them to the module: - explode_interface_port(new_ast, intfmodule, name_port, modport); + explode_interface_port(new_ast.get(), intfmodule, name_port, modport); } break; } @@ -1642,9 +1641,7 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dictset_bool_attribute(ID::interfaces_replaced_in_module); @@ -1654,7 +1651,7 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict ¶meters, const dict &interfaces, const dict &modports, bool /*mayfail*/) { - AstNode *new_ast = NULL; + std::unique_ptr new_ast = NULL; std::string modname = derive_common(design, parameters, &new_ast); // Since interfaces themselves may be instantiated with different parameters, @@ -1690,14 +1687,14 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict 0) { std::string interface_modport = modports.at(intfname).str(); AstModule *ast_module_of_interface = (AstModule*)intfmodule; - AstNode *ast_node_of_interface = ast_module_of_interface->ast; + AstNode *ast_node_of_interface = ast_module_of_interface->ast.get(); modport = find_modport(ast_node_of_interface, interface_modport); } // Iterate over all wires in the interface and add them to the module: - explode_interface_port(new_ast, intfmodule, intfname, modport); + explode_interface_port(new_ast.get(), intfmodule, intfname, modport); } - process_module(design, new_ast, false); + process_module(design, new_ast.get(), false); design->module(modname)->check(); RTLIL::Module* mod = design->module(modname); @@ -1734,7 +1731,6 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict new_ast = NULL; std::string modname = derive_common(design, parameters, &new_ast, quiet); if (!design->has(modname) && new_ast) { new_ast->str = modname; - process_module(design, new_ast, false, NULL, quiet); + process_module(design, new_ast.get(), false, NULL, quiet); design->module(modname)->check(); } else if (!quiet) { log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); } - delete new_ast; return modname; } @@ -1784,7 +1779,7 @@ std::string AST::derived_module_name(std::string stripped_name, const std::vecto } // create a new parametric module (when needed) and return the name of the generated module -std::string AstModule::derive_common(RTLIL::Design *design, const dict ¶meters, AstNode **new_ast_out, bool quiet) +std::string AstModule::derive_common(RTLIL::Design *design, const dict ¶meters, std::unique_ptr* new_ast_out, bool quiet) { std::string stripped_name = name.str(); (*new_ast_out) = nullptr; @@ -1794,7 +1789,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict> named_parameters; - for (const auto child : ast->children) { + for (const auto& child : ast->children) { if (child->type != AST_PARAMETER) continue; para_counter++; @@ -1828,12 +1823,12 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict rewritten; rewritten.reserve(GetSize(parameters)); - AstNode *new_ast = ast->clone(); + auto new_ast = ast->clone(); if (!new_ast->attributes.count(ID::hdlname)) new_ast->set_attribute(ID::hdlname, AstNode::mkconst_str(stripped_name.substr(1))); para_counter = 0; - for (auto child : new_ast->children) { + for (auto& child : new_ast->children) { if (child->type != AST_PARAMETER) continue; para_counter++; @@ -1853,9 +1848,8 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dictchildren.insert(child->children.begin(), nullptr); - delete child->children.at(0); if ((it->second.flags & RTLIL::CONST_FLAG_REAL) != 0) { - child->children[0] = new AstNode(AST_REALVALUE); + child->children[0] = std::make_unique(AST_REALVALUE); child->children[0]->realvalue = std::stod(it->second.decode_string()); } else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0) child->children[0] = AstNode::mkconst_str(it->second.decode_string()); @@ -1868,17 +1862,17 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict(AST_DEFPARAM, std::make_unique(AST_IDENTIFIER)); defparam->children[0]->str = param.first.str(); if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0) defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string())); else defparam->children.push_back(AstNode::mkconst_bits(param.second.to_bits(), (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0)); - new_ast->children.push_back(defparam); + new_ast->children.push_back(std::move(defparam)); } new_ast->fixup_hierarchy_flags(true); - (*new_ast_out) = new_ast; + new_ast_out->reset(new_ast.release()); return modname; } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 2c2d408ce..7d6390db7 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -183,10 +183,10 @@ namespace AST AstNodeType type; // the list of child nodes for this node - std::vector children; + std::vector> children; // the list of attributes assigned to this node - std::map attributes; + std::map> attributes; bool get_bool_attribute(RTLIL::IdString id); // node content - most of it is unused in most node types @@ -212,7 +212,7 @@ namespace AST int unpacked_dimensions; // this is set by simplify and used during RTLIL generation - AstNode *id2ast; + AstNode* id2ast; // this is used by simplify to detect if basic analysis has been performed already on the node bool basic_prep; @@ -234,9 +234,9 @@ namespace AST bool in_param_from_above; // creating and deleting nodes - AstNode(AstNodeType type = AST_NONE, AstNode *child1 = nullptr, AstNode *child2 = nullptr, AstNode *child3 = nullptr, AstNode *child4 = nullptr); - AstNode *clone() const; - void cloneInto(AstNode *other) const; + AstNode(AstNodeType type = AST_NONE, std::unique_ptr child1 = nullptr, std::unique_ptr child2 = nullptr, std::unique_ptr child3 = nullptr, std::unique_ptr child4 = nullptr); + std::unique_ptr clone() const; + void cloneInto(AstNode &other) const; void delete_children(); ~AstNode(); @@ -264,15 +264,16 @@ namespace AST // simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc. // it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL() bool simplify(bool const_fold, int stage, int width_hint, bool sign_hint); + void null_check(); void replace_result_wire_name_in_function(const std::string &from, const std::string &to); - AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init); + std::unique_ptr readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init); void expand_genblock(const std::string &prefix); void label_genblks(std::set& existing, int &counter); void mem2reg_as_needed_pass1(dict> &mem2reg_places, dict &mem2reg_flags, dict &proc_flags, uint32_t &status_flags); - bool mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block); + bool mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *block, AstNode* async_block); bool mem2reg_check(pool &mem2reg_set); - void mem2reg_remove(pool &mem2reg_set, vector &delnodes); + void mem2reg_remove(pool &mem2reg_set); void meminfo(int &mem_width, int &mem_size, int &addr_bits); bool detect_latch(const std::string &var); const RTLIL::Module* lookup_cell_module(); @@ -288,7 +289,7 @@ namespace AST }; bool has_const_only_constructs(); bool replace_variables(std::map &variables, AstNode *fcall, bool must_succeed); - AstNode *eval_const_function(AstNode *fcall, bool must_succeed); + std::unique_ptr eval_const_function(AstNode *fcall, bool must_succeed); bool is_simple_const_expr(); // helper for parsing format strings @@ -305,29 +306,30 @@ namespace AST std::vector genBindings() const; // used by genRTLIL() for detecting expression width and sign - void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = NULL); - void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real = NULL); + void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = nullptr); + void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real = nullptr); // create RTLIL code for this AST node // for expressions the resulting signal vector is returned // all generated cell instances, etc. are written to the RTLIL::Module pointed to by AST_INTERNAL::current_module RTLIL::SigSpec genRTLIL(int width_hint = -1, bool sign_hint = false); - RTLIL::SigSpec genWidthRTLIL(int width, bool sgn, const dict *new_subst_ptr = NULL); + RTLIL::SigSpec genWidthRTLIL(int width, bool sgn, const dict *new_subst_ptr = nullptr); // compare AST nodes bool operator==(const AstNode &other) const; bool operator!=(const AstNode &other) const; bool contains(const AstNode *other) const; + AstNode operator=(AstNode) = delete; // helper functions for creating AST nodes for constants - static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32); - static AstNode *mkconst_bits(const std::vector &v, bool is_signed, bool is_unsized); - static AstNode *mkconst_bits(const std::vector &v, bool is_signed); - static AstNode *mkconst_str(const std::vector &v); - static AstNode *mkconst_str(const std::string &str); + static std::unique_ptr mkconst_int(uint32_t v, bool is_signed, int width = 32); + static std::unique_ptr mkconst_bits(const std::vector &v, bool is_signed, bool is_unsized); + static std::unique_ptr mkconst_bits(const std::vector &v, bool is_signed); + static std::unique_ptr mkconst_str(const std::vector &v); + static std::unique_ptr mkconst_str(const std::string &str); // helper function to create an AST node for a temporary register - AstNode *mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed); + std::unique_ptr mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed); // helper function for creating sign-extended const objects RTLIL::Const bitsAsConst(int width, bool is_signed); @@ -356,12 +358,12 @@ namespace AST // helper to clone the node with some of its subexpressions replaced with zero (this is used // to evaluate widths of dynamic ranges) - AstNode *clone_at_zero(); + std::unique_ptr clone_at_zero(); - void set_attribute(RTLIL::IdString key, AstNode *node) + void set_attribute(RTLIL::IdString key, std::unique_ptr node) { - attributes[key] = node; node->set_in_param_flag(true); + attributes[key] = std::move(node); } // helper to set in_lvalue/in_param flags from the hierarchy context (the actual flag @@ -377,7 +379,7 @@ namespace AST void fixup_hierarchy_flags(bool force_descend = false); // helpers for indexing - AstNode *make_index_range(AstNode *node, bool unpacked_range = false); + std::unique_ptr make_index_range(AstNode *node, bool unpacked_range = false); AstNode *get_struct_member() const; // helper to print errors from simplify/genrtlil code @@ -391,12 +393,11 @@ namespace AST // parametric modules are supported directly by the AST library // therefore we need our own derivate of RTLIL::Module with overloaded virtual functions struct AstModule : RTLIL::Module { - AstNode *ast; + std::unique_ptr ast; bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire; - ~AstModule() override; RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, bool mayfail) override; RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, const dict &interfaces, const dict &modports, bool mayfail) override; - std::string derive_common(RTLIL::Design *design, const dict ¶meters, AstNode **new_ast_out, bool quiet = false); + std::string derive_common(RTLIL::Design *design, const dict ¶meters, std::unique_ptr* new_ast_out, bool quiet = false); void expand_interfaces(RTLIL::Design *design, const dict &local_interfaces) override; bool reprocess_if_necessary(RTLIL::Design *design) override; RTLIL::Module *clone() const override; @@ -407,8 +408,6 @@ namespace AST // the AstNode constructor then uses current_filename and get_line_num() // to initialize the filename and linenum properties of new nodes extern std::string current_filename; - extern void (*set_line_num)(int); - extern int (*get_line_num)(); // for stats unsigned long long astnode_count(); @@ -418,7 +417,7 @@ namespace AST void use_internal_line_num(); // call a DPI function - AstNode *dpi_call(const std::string &rtype, const std::string &fname, const std::vector &argtypes, const std::vector &args); + std::unique_ptr dpi_call(const std::string &rtype, const std::string &fname, const std::vector &argtypes, const std::vector> &args); // Helper functions related to handling SystemVerilog interfaces std::pair split_modport_from_type(std::string name_type); @@ -464,7 +463,7 @@ namespace AST_INTERNAL process_and_replace_module(RTLIL::Design *design, RTLIL::Module *old_module, AST::AstNode *new_ast, - AST::AstNode *original_ast = nullptr); + std::unique_ptr original_ast = nullptr); } YOSYS_NAMESPACE_END diff --git a/frontends/ast/dpicall.cc b/frontends/ast/dpicall.cc index d6fcc26bd..4fa375df7 100644 --- a/frontends/ast/dpicall.cc +++ b/frontends/ast/dpicall.cc @@ -64,9 +64,9 @@ static ffi_fptr resolve_fn (std::string symbol_name) log_error("unable to resolve '%s'.\n", symbol_name.c_str()); } -AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, const std::vector &argtypes, const std::vector &args) +std::unique_ptr AST::dpi_call(const std::string &rtype, const std::string &fname, const std::vector &argtypes, const std::vector> &args) { - AST::AstNode *newNode = nullptr; + std::unique_ptr newNode = nullptr; union value { double f64; float f32; int32_t i32; void *ptr; }; std::vector value_store(args.size() + 1); std::vector types(args.size() + 1); @@ -125,11 +125,11 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, ffi_call(&cif, resolve_fn(fname.c_str()), values[args.size()], values.data()); if (rtype == "real") { - newNode = new AstNode(AST_REALVALUE); + newNode = std::make_unique(AST_REALVALUE); newNode->realvalue = value_store[args.size()].f64; log(" return realvalue: %g\n", newNode->asReal(true)); } else if (rtype == "shortreal") { - newNode = new AstNode(AST_REALVALUE); + newNode = std::make_unique(AST_REALVALUE); newNode->realvalue = value_store[args.size()].f32; log(" return realvalue: %g\n", newNode->asReal(true)); } else if (rtype == "chandle") { diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 26ed0e3e4..fcc91adfc 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -85,7 +85,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s set_src_attr(wire, that); wire->is_signed = that->is_signed; - if (that != NULL) + if (that != nullptr) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) that->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str()); @@ -195,22 +195,22 @@ struct AST_INTERNAL::LookaheadRewriter if (node->lookahead) { log_assert(node->type == AST_IDENTIFIER); if (!lookaheadids.count(node->str)) { - AstNode *wire = new AstNode(AST_WIRE); - for (auto c : node->id2ast->children) + auto wire = std::make_unique(AST_WIRE); + for (auto& c : node->id2ast->children) wire->children.push_back(c->clone()); wire->fixup_hierarchy_flags(); wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++); wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); wire->is_logic = true; while (wire->simplify(true, 1, -1, false)) { } - current_ast_mod->children.push_back(wire); - lookaheadids[node->str] = make_pair(node->id2ast, wire); + lookaheadids[node->str] = make_pair(node->id2ast, wire.get()); wire->genRTLIL(); + current_ast_mod->children.push_back(std::move(wire)); } } - for (auto child : node->children) - collect_lookaheadids(child); + for (auto& child : node->children) + collect_lookaheadids(child.get()); } bool has_lookaheadids(AstNode *node) @@ -218,8 +218,8 @@ struct AST_INTERNAL::LookaheadRewriter if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) != 0) return true; - for (auto child : node->children) - if (has_lookaheadids(child)) + for (auto& child : node->children) + if (has_lookaheadids(child.get())) return true; return false; @@ -230,8 +230,8 @@ struct AST_INTERNAL::LookaheadRewriter if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) == 0) return true; - for (auto child : node->children) - if (has_nonlookaheadids(child)) + for (auto& child : node->children) + if (has_nonlookaheadids(child.get())) return true; return false; @@ -241,16 +241,16 @@ struct AST_INTERNAL::LookaheadRewriter { if (node->type == AST_ASSIGN_LE) { - if (has_lookaheadids(node->children[0])) + if (has_lookaheadids(node->children[0].get())) { - if (has_nonlookaheadids(node->children[0])) + if (has_nonlookaheadids(node->children[0].get())) log_error("incompatible mix of lookahead and non-lookahead IDs in LHS expression.\n"); - rewrite_lookaheadids(node->children[0], true); + rewrite_lookaheadids(node->children[0].get(), true); node->type = AST_ASSIGN_EQ; } - rewrite_lookaheadids(node->children[1], lhs); + rewrite_lookaheadids(node->children[1].get(), lhs); return; } @@ -261,21 +261,21 @@ struct AST_INTERNAL::LookaheadRewriter lhs = false; } - for (auto child : node->children) - rewrite_lookaheadids(child, lhs); + for (auto& child : node->children) + rewrite_lookaheadids(child.get(), lhs); } LookaheadRewriter(AstNode *top) { - // top->dumpAst(NULL, "REWRITE-BEFORE> "); - // top->dumpVlog(NULL, "REWRITE-BEFORE> "); + // top->dumpAst(nullptr, "REWRITE-BEFORE> "); + // top->dumpVlog(nullptr, "REWRITE-BEFORE> "); AstNode *block = nullptr; - for (auto c : top->children) + for (auto& c : top->children) if (c->type == AST_BLOCK) { log_assert(block == nullptr); - block = c; + block = c.get(); } log_assert(block != nullptr); @@ -284,25 +284,25 @@ struct AST_INTERNAL::LookaheadRewriter for (auto it : lookaheadids) { - AstNode *ref_orig = new AstNode(AST_IDENTIFIER); + auto ref_orig = std::make_unique(AST_IDENTIFIER); ref_orig->str = it.second.first->str; ref_orig->id2ast = it.second.first; ref_orig->was_checked = true; - AstNode *ref_temp = new AstNode(AST_IDENTIFIER); + auto ref_temp = std::make_unique(AST_IDENTIFIER); ref_temp->str = it.second.second->str; ref_temp->id2ast = it.second.second; ref_temp->was_checked = true; - AstNode *init_assign = new AstNode(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone()); - AstNode *final_assign = new AstNode(AST_ASSIGN_LE, ref_orig, ref_temp); + auto init_assign = std::make_unique(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone()); + auto final_assign = std::make_unique(AST_ASSIGN_LE, std::move(ref_orig), std::move(ref_temp)); - block->children.insert(block->children.begin(), init_assign); - block->children.push_back(final_assign); + block->children.insert(block->children.begin(), std::move(init_assign)); + block->children.push_back(std::move(final_assign)); } - // top->dumpAst(NULL, "REWRITE-AFTER> "); - // top->dumpVlog(NULL, "REWRITE-AFTER> "); + // top->dumpAst(nullptr, "REWRITE-AFTER> "); + // top->dumpVlog(nullptr, "REWRITE-AFTER> "); } }; @@ -310,7 +310,7 @@ struct AST_INTERNAL::LookaheadRewriter struct AST_INTERNAL::ProcessGenerator { // input and output structures - AstNode *always; + std::unique_ptr always; RTLIL::SigSpec initSyncSignals; RTLIL::Process *proc; RTLIL::SigSpec outputSignals; @@ -341,14 +341,14 @@ struct AST_INTERNAL::ProcessGenerator // The most recently assigned $print or $check cell \PRIORITY. int last_effect_priority; - ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg), last_effect_priority(0) + ProcessGenerator(std::unique_ptr a, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(std::move(a)), initSyncSignals(initSyncSignalsArg), last_effect_priority(0) { // rewrite lookahead references - LookaheadRewriter la_rewriter(always); + LookaheadRewriter la_rewriter(always.get()); // generate process and simple root case proc = current_module->addProcess(stringf("$proc$%s:%d$%d", RTLIL::encode_filename(always->filename).c_str(), always->location.first_line, autoidx++)); - set_src_attr(proc, always); + set_src_attr(proc, always.get()); for (auto &attr : always->attributes) { if (attr.second->type != AST_CONSTANT) always->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str()); @@ -358,13 +358,13 @@ struct AST_INTERNAL::ProcessGenerator // create initial temporary signal for all output registers RTLIL::SigSpec subst_lvalue_from, subst_lvalue_to; - collect_lvalues(subst_lvalue_from, always, true, true); + collect_lvalues(subst_lvalue_from, always.get(), true, true); subst_lvalue_to = new_temp_signal(subst_lvalue_from); subst_lvalue_map = subst_lvalue_from.to_sigbit_map(subst_lvalue_to); bool found_global_syncs = false; bool found_anyedge_syncs = false; - for (auto child : always->children) + for (auto& child : always->children) { if ((child->type == AST_POSEDGE || child->type == AST_NEGEDGE) && GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk)) { @@ -388,7 +388,7 @@ struct AST_INTERNAL::ProcessGenerator // create syncs for the process bool found_clocked_sync = false; - for (auto child : always->children) + for (auto& child : always->children) if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) { if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk)) @@ -420,9 +420,9 @@ struct AST_INTERNAL::ProcessGenerator } // process the AST - for (auto child : always->children) + for (auto& child : always->children) if (child->type == AST_BLOCK) - processAst(child); + processAst(child.get()); for (auto sync: proc->syncs) processMemWrites(sync); @@ -472,7 +472,7 @@ struct AST_INTERNAL::ProcessGenerator for (int i = 0; i < GetSize(chunks); i++) { RTLIL::SigChunk &chunk = chunks[i]; - if (chunk.wire == NULL) + if (chunk.wire == nullptr) continue; std::string wire_name; @@ -484,7 +484,7 @@ struct AST_INTERNAL::ProcessGenerator } while (current_module->wires_.count(wire_name) > 0); RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width); - set_src_attr(wire, always); + set_src_attr(wire, always.get()); chunk.wire = wire; chunk.offset = 0; @@ -499,10 +499,10 @@ struct AST_INTERNAL::ProcessGenerator switch (ast->type) { case AST_CASE: - for (auto child : ast->children) + for (auto& child : ast->children) if (child != ast->children[0]) { log_assert(child->type == AST_COND || child->type == AST_CONDX || child->type == AST_CONDZ); - collect_lvalues(reg, child, type_eq, type_le, false); + collect_lvalues(reg, child.get(), type_eq, type_le, false); } break; @@ -511,19 +511,19 @@ struct AST_INTERNAL::ProcessGenerator case AST_CONDZ: case AST_ALWAYS: case AST_INITIAL: - for (auto child : ast->children) + for (auto& child : ast->children) if (child->type == AST_BLOCK) - collect_lvalues(reg, child, type_eq, type_le, false); + collect_lvalues(reg, child.get(), type_eq, type_le, false); break; case AST_BLOCK: - for (auto child : ast->children) { + for (auto& child : ast->children) { if (child->type == AST_ASSIGN_EQ && type_eq) reg.append(child->children[0]->genRTLIL()); if (child->type == AST_ASSIGN_LE && type_le) reg.append(child->children[0]->genRTLIL()); if (child->type == AST_CASE || child->type == AST_BLOCK) - collect_lvalues(reg, child, type_eq, type_le, false); + collect_lvalues(reg, child.get(), type_eq, type_le, false); } break; @@ -583,8 +583,8 @@ struct AST_INTERNAL::ProcessGenerator switch (ast->type) { case AST_BLOCK: - for (auto child : ast->children) - processAst(child); + for (auto& child : ast->children) + processAst(child.get()); break; case AST_ASSIGN_EQ: @@ -641,9 +641,9 @@ struct AST_INTERNAL::ProcessGenerator RTLIL::SigSpec this_case_eq_rvalue = this_case_eq_lvalue; this_case_eq_rvalue.replace(subst_rvalue_map.stdmap()); - RTLIL::CaseRule *default_case = NULL; - RTLIL::CaseRule *last_generated_case = NULL; - for (auto child : ast->children) + RTLIL::CaseRule *default_case = nullptr; + RTLIL::CaseRule *last_generated_case = nullptr; + for (auto& child : ast->children) { if (child == ast->children[0]) continue; @@ -657,14 +657,14 @@ struct AST_INTERNAL::ProcessGenerator RTLIL::CaseRule *backup_case = current_case; current_case = new RTLIL::CaseRule; - set_src_attr(current_case, child); + set_src_attr(current_case, child.get()); last_generated_case = current_case; addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue); - for (auto node : child->children) { + for (auto& node : child->children) { if (node->type == AST_DEFAULT) default_case = current_case; else if (node->type == AST_BLOCK) - processAst(node); + processAst(node.get()); else current_case->compare.push_back(node->genWidthRTLIL(width_hint, sign_hint, &subst_rvalue_map.stdmap())); } @@ -678,7 +678,7 @@ struct AST_INTERNAL::ProcessGenerator subst_rvalue_map.restore(); } - if (last_generated_case != NULL && ast->get_bool_attribute(ID::full_case) && default_case == NULL) { + if (last_generated_case != nullptr && ast->get_bool_attribute(ID::full_case) && default_case == nullptr) { #if 0 // this is a valid transformation, but as optimization it is premature. // better: add a default case that assigns 'x' to everything, and let later @@ -690,7 +690,7 @@ struct AST_INTERNAL::ProcessGenerator sw->cases.push_back(default_case); #endif } else { - if (default_case == NULL) { + if (default_case == nullptr) { default_case = new RTLIL::CaseRule; addChunkActions(default_case->actions, this_case_eq_ltemp, this_case_eq_rvalue); } @@ -760,7 +760,7 @@ struct AST_INTERNAL::ProcessGenerator default_base = 16; std::vector args; - for (auto node : ast->children) { + for (auto& node : ast->children) { int width; bool is_signed; node->detectSignWidth(width, is_signed, nullptr); @@ -866,8 +866,8 @@ struct AST_INTERNAL::ProcessGenerator break; default: - // ast->dumpAst(NULL, "ast> "); - // current_ast_mod->dumpAst(NULL, "mod> "); + // ast->dumpAst(nullptr, "ast> "); + // current_ast_mod->dumpAst(nullptr, "mod> "); log_abort(); } } @@ -876,14 +876,14 @@ struct AST_INTERNAL::ProcessGenerator { // Maps per-memid AST_MEMWR IDs to indices in the mem_write_actions array. dict, int> port_map; - for (auto child : always->children) + for (auto& child : always->children) if (child->type == AST_MEMWR) { std::string memid = child->str; int portid = child->children[3]->asInt(false); int cur_idx = GetSize(sync->mem_write_actions); RTLIL::MemWriteAction action; - set_src_attr(&action, child); + set_src_attr(&action, child.get()); action.memid = memid; action.address = child->children[0]->genWidthRTLIL(-1, true, &subst_rvalue_map.stdmap()); action.data = child->children[1]->genWidthRTLIL(current_module->memories[memid]->width, true, &subst_rvalue_map.stdmap()); @@ -971,11 +971,11 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun bool sub_sign_hint = true; int sub_width_hint = -1; int this_width = 0; - AstNode *range = NULL; - AstNode *id_ast = NULL; + AstNode *range = nullptr; + AstNode *id_ast = nullptr; bool local_found_real = false; - if (found_real == NULL) + if (found_real == nullptr) found_real = &local_found_real; switch (type) @@ -1019,22 +1019,22 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun input_error("Failed to detect width for parameter %s!\n", str.c_str()); } if (children.size() != 0) - range = children[0]; + range = children[0].get(); } else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) { if (!id_ast->range_valid) { if (id_ast->type == AST_AUTOWIRE) this_width = 1; else { - // current_ast_mod->dumpAst(NULL, "mod> "); + // current_ast_mod->dumpAst(nullptr, "mod> "); // log("---\n"); - // id_ast->dumpAst(NULL, "decl> "); - // dumpAst(NULL, "ref> "); + // id_ast->dumpAst(nullptr, "decl> "); + // dumpAst(nullptr, "ref> "); input_error("Failed to detect width of signal access `%s'!\n", str.c_str()); } } else { this_width = id_ast->range_left - id_ast->range_right + 1; if (children.size() != 0) - range = children[0]; + range = children[0].get(); } } else if (id_ast->type == AST_GENVAR) { this_width = 32; @@ -1043,26 +1043,23 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun input_error("Failed to detect width of memory access `%s'!\n", str.c_str()); this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1; if (children.size() > 1) - range = children[1]; + range = children[1].get(); } else if (id_ast->type == AST_STRUCT_ITEM || id_ast->type == AST_STRUCT || id_ast->type == AST_UNION) { - AstNode *tmp_range = make_index_range(id_ast); + auto tmp_range = make_index_range(id_ast); this_width = tmp_range->range_left - tmp_range->range_right + 1; - delete tmp_range; } else input_error("Failed to detect width for identifier %s!\n", str.c_str()); if (range) { if (range->children.size() == 1) this_width = 1; else if (!range->range_valid) { - AstNode *left_at_zero_ast = children[0]->children[0]->clone_at_zero(); - AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone(); + auto left_at_zero_ast = children[0]->children[0]->clone_at_zero(); + auto right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone(); while (left_at_zero_ast->simplify(true, 1, -1, false)) { } while (right_at_zero_ast->simplify(true, 1, -1, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); this_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; - delete left_at_zero_ast; - delete right_at_zero_ast; } else this_width = range->range_left - range->range_right + 1; sign_hint = false; @@ -1106,7 +1103,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun break; case AST_CONCAT: - for (auto child : children) { + for (auto& child : children) { sub_width_hint = 0; sub_sign_hint = true; child->detectSignWidthWorker(sub_width_hint, sub_sign_hint); @@ -1135,7 +1132,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_BIT_OR: case AST_BIT_XOR: case AST_BIT_XNOR: - for (auto child : children) + for (auto& child : children) child->detectSignWidthWorker(width_hint, sign_hint, found_real); break; @@ -1175,7 +1172,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_MUL: case AST_DIV: case AST_MOD: - for (auto child : children) + for (auto& child : children) child->detectSignWidthWorker(width_hint, sign_hint, found_real); break; @@ -1216,12 +1213,13 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun width_hint = max(width_hint, sub_width_hint); sign_hint &= sub_sign_hint; }; - visit_case_expr(children[0]); + visit_case_expr(children[0].get()); for (size_t i = 1; i < children.size(); i++) { - AstNode *child = children[i]; - for (AstNode *v : child->children) + AstNode *child = children[i].get(); + for (auto& v : child->children) { if (v->type != AST_DEFAULT && v->type != AST_BLOCK) - visit_case_expr(v); + visit_case_expr(v.get()); + } } break; } @@ -1269,9 +1267,9 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (func->type != AST_FUNCTION) input_error("Function call to %s resolved to something that isn't a function!\n", RTLIL::unescape_id(str).c_str()); const AstNode *wire = nullptr; - for (const AstNode *child : func->children) + for (const auto& child : func->children) if (child->str == func->str) { - wire = child; + wire = child.get(); break; } log_assert(wire && wire->type == AST_WIRE); @@ -1280,10 +1278,10 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (!wire->children.empty()) { log_assert(wire->children.size() == 1); - const AstNode *range = wire->children.at(0); + const AstNode *range = wire->children.at(0).get(); log_assert(range->type == AST_RANGE && range->children.size() == 2); - AstNode *left = range->children.at(0)->clone(); - AstNode *right = range->children.at(1)->clone(); + auto left = range->children.at(0)->clone(); + auto right = range->children.at(1)->clone(); left->set_in_param_flag(true); right->set_in_param_flag(true); while (left->simplify(true, 1, -1, false)) { } @@ -1292,8 +1290,6 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun input_error("Function %s has non-constant width!", RTLIL::unescape_id(str).c_str()); result_width = abs(int(left->asInt(true) - right->asInt(true))); - delete left; - delete right; } width_hint = max(width_hint, result_width); break; @@ -1306,6 +1302,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun for (auto f : log_files) current_scope_ast->dumpAst(f, "verilog-ast> "); input_error("Don't know how to detect sign and width for %s node!\n", type2str(type).c_str()); + } if (*found_real) @@ -1517,11 +1514,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // shifter cell is created and the output signal of this cell is returned case AST_IDENTIFIER: { - RTLIL::Wire *wire = NULL; + RTLIL::Wire *wire = nullptr; RTLIL::SigChunk chunk; bool is_interface = false; - AST::AstNode *member_node = NULL; + AST::AstNode *member_node = nullptr; int add_undef_bits_msb = 0; int add_undef_bits_lsb = 0; @@ -1608,14 +1605,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } if (!children[0]->range_valid) { - AstNode *left_at_zero_ast = children[0]->children[0]->clone_at_zero(); - AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone(); + auto left_at_zero_ast = children[0]->children[0]->clone_at_zero(); + auto right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone(); while (left_at_zero_ast->simplify(true, 1, -1, false)) { } while (right_at_zero_ast->simplify(true, 1, -1, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; - AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ? + auto fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : children[0]->children[0]->clone()); fake_ast->children[0]->delete_children(); if (member_node) @@ -1637,9 +1634,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (GetSize(shift_val) >= 32) fake_ast->children[1]->is_signed = true; RTLIL::SigSpec sig = binop2rtlil(fake_ast, ID($shiftx), width, fake_ast->children[0]->genRTLIL(), shift_val); - delete left_at_zero_ast; - delete right_at_zero_ast; - delete fake_ast; return sig; } else { chunk.width = children[0]->range_left - children[0]->range_right + 1; @@ -2092,7 +2086,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) cell->set_bool_attribute(ID::module_not_derived); for (auto it = children.begin(); it != children.end(); it++) { - AstNode *child = *it; + AstNode *child = it->get(); if (child->type == AST_CELLTYPE) { cell->type = child->str; if (flag_icells && cell->type.begins_with("\\$")) @@ -2101,7 +2095,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } if (child->type == AST_PARASET) { IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str; - const AstNode *value = child->children[0]; + const AstNode *value = child->children[0].get(); if (value->type == AST_REALVALUE) log_file_warning(filename, location.first_line, "Replacing floating point parameter %s.%s = %f with string.\n", log_id(cell), log_id(paraname), value->realvalue); @@ -2114,7 +2108,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (child->type == AST_ARGUMENT) { RTLIL::SigSpec sig; if (child->children.size() > 0) { - AstNode *arg = child->children[0]; + AstNode *arg = child->children[0].get(); int local_width_hint = -1; bool local_sign_hint = false; // don't inadvertently attempt to detect the width of interfaces @@ -2186,16 +2180,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // use ProcessGenerator for always blocks case AST_ALWAYS: { - AstNode *always = this->clone(); - ProcessGenerator generator(always); + auto always = this->clone(); + ProcessGenerator generator(std::move(always)); ignoreThisSignalsInInitial.append(generator.outputSignals); - delete always; } break; case AST_INITIAL: { - AstNode *always = this->clone(); - ProcessGenerator generator(always, ignoreThisSignalsInInitial); - delete always; + auto always = this->clone(); + ProcessGenerator generator(std::move(always), ignoreThisSignalsInInitial); } break; case AST_TECALL: { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 55087c772..20372215a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -87,7 +87,7 @@ void AstNode::fixup_hierarchy_flags(bool force_descend) case AST_PARASET: case AST_PREFIX: in_param = true; - for (auto child : children) + for (auto& child : children) child->set_in_param_flag(true, force_descend); break; @@ -95,7 +95,7 @@ void AstNode::fixup_hierarchy_flags(bool force_descend) case AST_WIRE: case AST_GENIF: case AST_GENCASE: - for (auto child : children) + for (auto& child : children) child->set_in_param_flag(in_param, force_descend); if (children.size() >= 1) children[0]->set_in_param_flag(true, force_descend); @@ -103,19 +103,21 @@ void AstNode::fixup_hierarchy_flags(bool force_descend) case AST_GENFOR: case AST_FOR: - for (auto child : children) + for (auto& child : children) { + log_assert((bool)child); child->set_in_param_flag(in_param, force_descend); + } if (children.size() >= 2) children[1]->set_in_param_flag(true, force_descend); break; default: in_param = in_param_from_above; - for (auto child : children) + for (auto& child : children) child->set_in_param_flag(in_param, force_descend); } - for (auto attr : attributes) + for (auto& attr : attributes) attr.second->set_in_param_flag(true, force_descend); in_lvalue = in_lvalue_from_above; @@ -131,14 +133,14 @@ void AstNode::fixup_hierarchy_flags(bool force_descend) break; default: - for (auto child : children) + for (auto& child : children) child->set_in_lvalue_flag(in_lvalue, force_descend); } if (force_descend) { - for (auto child : children) + for (auto& child : children) child->fixup_hierarchy_flags(true); - for (auto attr : attributes) + for (auto& attr : attributes) attr.second->fixup_hierarchy_flags(true); } } @@ -148,7 +150,7 @@ void AstNode::fixup_hierarchy_flags(bool force_descend) Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_t first_arg_at, bool may_fail) { std::vector args; for (size_t index = first_arg_at; index < children.size(); index++) { - AstNode *node_arg = children[index]; + AstNode *node_arg = children[index].get(); while (node_arg->simplify(true, stage, -1, false)) { } VerilogFmtArg arg = {}; @@ -199,7 +201,7 @@ void AstNode::annotateTypedEnums(AstNode *template_node) while (enum_node->simplify(true, 1, -1, false)) { } //get width from 1st enum item: log_assert(enum_node->children.size() >= 1); - AstNode *enum_item0 = enum_node->children[0]; + AstNode *enum_item0 = enum_node->children[0].get(); log_assert(enum_item0->type == AST_ENUM_ITEM); int width; if (!enum_item0->range_valid) @@ -210,7 +212,7 @@ void AstNode::annotateTypedEnums(AstNode *template_node) width = enum_item0->range_left - enum_item0->range_right + 1; log_assert(width > 0); //add declared enum items: - for (auto enum_item : enum_node->children){ + for (auto& enum_item : enum_node->children){ log_assert(enum_item->type == AST_ENUM_ITEM); //get is_signed bool is_signed; @@ -242,10 +244,10 @@ void AstNode::annotateTypedEnums(AstNode *template_node) } } -static AstNode *make_range(int left, int right, bool is_signed = false) +static std::unique_ptr make_range(int left, int right, bool is_signed = false) { // generate a pre-validated range node for a fixed signal range. - auto range = new AstNode(AST_RANGE); + auto range = std::make_unique(AST_RANGE); range->range_left = left; range->range_right = right; range->range_valid = true; @@ -287,7 +289,7 @@ static int size_packed_struct(AstNode *snode, int base_offset) int packed_width = -1; // examine members from last to first for (auto it = snode->children.rbegin(); it != snode->children.rend(); ++it) { - auto node = *it; + auto node = it->get(); int width; if (node->type == AST_STRUCT || node->type == AST_UNION) { // embedded struct or union @@ -297,14 +299,14 @@ static int size_packed_struct(AstNode *snode, int base_offset) log_assert(node->type == AST_STRUCT_ITEM); if (node->children.size() > 0 && node->children[0]->type == AST_RANGE) { // member width e.g. bit [7:0] a - width = range_width(node, node->children[0]); + width = range_width(node, node->children[0].get()); if (node->children.size() == 2) { // Unpacked array. Note that this is a Yosys extension; only packed data types // and integer data types are allowed in packed structs / unions in SystemVerilog. if (node->children[1]->type == AST_RANGE) { // Unpacked array, e.g. bit [63:0] a [0:3] // Pretend it's declared as a packed array, e.g. bit [0:3][63:0] a - auto rnode = node->children[1]; + auto rnode = node->children[1].get(); if (rnode->children.size() == 1) { // C-style array size, e.g. bit [63:0] a [4] node->dimensions.push_back({ 0, rnode->range_left, true }); @@ -312,7 +314,7 @@ static int size_packed_struct(AstNode *snode, int base_offset) } else { width *= add_dimension(node, rnode); } - add_dimension(node, node->children[0]); + add_dimension(node, node->children[0].get()); } else { // The Yosys extension for unpacked arrays in packed structs / unions @@ -321,11 +323,9 @@ static int size_packed_struct(AstNode *snode, int base_offset) } } else { // Vector - add_dimension(node, node->children[0]); + add_dimension(node, node->children[0].get()); } // range nodes are now redundant - for (AstNode *child : node->children) - delete child; node->children.clear(); } else if (node->children.size() > 0 && node->children[0]->type == AST_MULTIRANGE) { @@ -336,12 +336,10 @@ static int size_packed_struct(AstNode *snode, int base_offset) struct_array_packing_error(node); } width = 1; - for (auto rnode : node->children[0]->children) { - width *= add_dimension(node, rnode); + for (auto& rnode : node->children[0]->children) { + width *= add_dimension(node, rnode.get()); } // range nodes are now redundant - for (AstNode *child : node->children) - delete child; node->children.clear(); } else if (node->range_left < 0) { @@ -389,49 +387,49 @@ static int size_packed_struct(AstNode *snode, int base_offset) return width; } -static AstNode *node_int(int ival) +static std::unique_ptr node_int(int ival) { return AstNode::mkconst_int(ival, true); } -static AstNode *multiply_by_const(AstNode *expr_node, int stride) +static std::unique_ptr multiply_by_const(std::unique_ptr expr_node, int stride) { - return new AstNode(AST_MUL, expr_node, node_int(stride)); + return std::make_unique(AST_MUL, std::move(expr_node), node_int(stride)); } -static AstNode *normalize_index(AstNode *expr, AstNode *decl_node, int dimension) +static std::unique_ptr normalize_index(AstNode *expr, AstNode *decl_node, int dimension) { - expr = expr->clone(); + auto new_expr = expr->clone(); int offset = decl_node->dimensions[dimension].range_right; if (offset) { - expr = new AstNode(AST_SUB, expr, node_int(offset)); + new_expr = std::make_unique(AST_SUB, std::move(new_expr), node_int(offset)); } // Packed dimensions are normally indexed by lsb, while unpacked dimensions are normally indexed by msb. if ((dimension < decl_node->unpacked_dimensions) ^ decl_node->dimensions[dimension].range_swapped) { // Swap the index if the dimension is declared the "wrong" way. int left = decl_node->dimensions[dimension].range_width - 1; - expr = new AstNode(AST_SUB, node_int(left), expr); + new_expr = std::make_unique(AST_SUB, node_int(left), std::move(new_expr)); } - return expr; + return new_expr; } -static AstNode *index_offset(AstNode *offset, AstNode *rnode, AstNode *decl_node, int dimension, int &stride) +static std::unique_ptr index_offset(std::unique_ptr offset, AstNode *rnode, AstNode *decl_node, int dimension, int &stride) { stride /= decl_node->dimensions[dimension].range_width; - auto right = normalize_index(rnode->children.back(), decl_node, dimension); - auto add_offset = stride > 1 ? multiply_by_const(right, stride) : right; - return offset ? new AstNode(AST_ADD, offset, add_offset) : add_offset; + auto right = normalize_index(rnode->children.back().get(), decl_node, dimension); + auto add_offset = stride > 1 ? multiply_by_const(std::move(right), stride) : std::move(right); + return offset ? std::make_unique(AST_ADD, std::move(offset), std::move(add_offset)) : std::move(add_offset); } -static AstNode *index_msb_offset(AstNode *lsb_offset, AstNode *rnode, AstNode *decl_node, int dimension, int stride) +static std::unique_ptr index_msb_offset(std::unique_ptr lsb_offset, AstNode *rnode, AstNode *decl_node, int dimension, int stride) { log_assert(rnode->children.size() <= 2); // Offset to add to LSB - AstNode *add_offset; + std::unique_ptr add_offset; if (rnode->children.size() == 1) { // Index, e.g. s.a[i] add_offset = node_int(stride - 1); @@ -439,21 +437,21 @@ static AstNode *index_msb_offset(AstNode *lsb_offset, AstNode *rnode, AstNode *d else { // rnode->children.size() == 2 // Slice, e.g. s.a[i:j] - auto left = normalize_index(rnode->children[0], decl_node, dimension); - auto right = normalize_index(rnode->children[1], decl_node, dimension); - add_offset = new AstNode(AST_SUB, left, right); + auto left = normalize_index(rnode->children[0].get(), decl_node, dimension); + auto right = normalize_index(rnode->children[1].get(), decl_node, dimension); + add_offset = std::make_unique(AST_SUB, std::move(left), std::move(right)); if (stride > 1) { // offset = (msb - lsb + 1)*stride - 1 - auto slice_width = new AstNode(AST_ADD, add_offset, node_int(1)); - add_offset = new AstNode(AST_SUB, multiply_by_const(slice_width, stride), node_int(1)); + auto slice_width = std::make_unique(AST_ADD, std::move(add_offset), node_int(1)); + add_offset = std::make_unique(AST_SUB, multiply_by_const(std::move(slice_width), stride), node_int(1)); } } - return new AstNode(AST_ADD, lsb_offset, add_offset); + return std::make_unique(AST_ADD, std::move(lsb_offset), std::move(add_offset)); } -AstNode *AstNode::make_index_range(AstNode *decl_node, bool unpacked_range) +std::unique_ptr AstNode::make_index_range(AstNode *decl_node, bool unpacked_range) { // Work out the range in the packed array that corresponds to a struct member // taking into account any range operations applicable to the current node @@ -466,8 +464,8 @@ AstNode *AstNode::make_index_range(AstNode *decl_node, bool unpacked_range) log_assert(children.size() == 1); // Range operations - AstNode *rnode = children[0]; - AstNode *offset = NULL; + AstNode *rnode = children[0].get(); + std::unique_ptr offset = nullptr; int dim = unpacked_range ? 0 : decl_node->unpacked_dimensions; int max_dim = unpacked_range ? decl_node->unpacked_dimensions : GetSize(decl_node->dimensions); @@ -478,15 +476,15 @@ AstNode *AstNode::make_index_range(AstNode *decl_node, bool unpacked_range) // Calculate LSB offset for the final index / slice if (rnode->type == AST_RANGE) { - offset = index_offset(offset, rnode, decl_node, dim, stride); + offset = index_offset(std::move(offset), rnode, decl_node, dim, stride); } else if (rnode->type == AST_MULTIRANGE) { // Add offset for each dimension AstNode *mrnode = rnode; int stop_dim = std::min(GetSize(mrnode->children), max_dim); for (; dim < stop_dim; dim++) { - rnode = mrnode->children[dim]; - offset = index_offset(offset, rnode, decl_node, dim, stride); + rnode = mrnode->children[dim].get(); + offset = index_offset(std::move(offset), rnode, decl_node, dim, stride); } dim--; // Step back to the final index / slice } @@ -494,15 +492,15 @@ AstNode *AstNode::make_index_range(AstNode *decl_node, bool unpacked_range) input_error("Unsupported range operation for %s\n", str.c_str()); } - AstNode *index_range = new AstNode(AST_RANGE); + std::unique_ptrindex_range = std::make_unique(AST_RANGE); if (!unpacked_range && (stride > 1 || GetSize(rnode->children) == 2)) { // Calculate MSB offset for the final index / slice of packed dimensions. - AstNode *msb_offset = index_msb_offset(offset->clone(), rnode, decl_node, dim, stride); - index_range->children.push_back(msb_offset); + std::unique_ptrmsb_offset = index_msb_offset(offset->clone(), rnode, decl_node, dim, stride); + index_range->children.push_back(std::move(msb_offset)); } - index_range->children.push_back(offset); + index_range->children.push_back(std::move(offset)); return index_range; } @@ -510,8 +508,8 @@ AstNode *AstNode::make_index_range(AstNode *decl_node, bool unpacked_range) AstNode *AstNode::get_struct_member() const { AstNode *member_node; - if (attributes.count(ID::wiretype) && (member_node = attributes.at(ID::wiretype)) && - (member_node->type == AST_STRUCT_ITEM || member_node->type == AST_STRUCT || member_node->type == AST_UNION)) + if (attributes.count(ID::wiretype) && (member_node = attributes.at(ID::wiretype).get()) && + (member_node->type == AST_STRUCT_ITEM || member_node->type == AST_STRUCT || member_node->type == AST_UNION)) { return member_node; } @@ -523,20 +521,20 @@ static void add_members_to_scope(AstNode *snode, std::string name) // add all the members in a struct or union to local scope // in case later referenced in assignments log_assert(snode->type==AST_STRUCT || snode->type==AST_UNION); - for (auto *node : snode->children) { + for (auto &node : snode->children) { auto member_name = name + "." + node->str; - current_scope[member_name] = node; + current_scope[member_name] = node.get(); if (node->type != AST_STRUCT_ITEM) { // embedded struct or union - add_members_to_scope(node, name + "." + node->str); + add_members_to_scope(node.get(), name + "." + node->str); } } } -static AstNode *make_packed_struct(AstNode *template_node, std::string &name, decltype(AstNode::attributes) &attributes) +std::unique_ptr make_packed_struct(AstNode *template_node, std::string &name, decltype(AstNode::attributes) &attributes) { // create a wire for the packed struct - auto wnode = new AstNode(AST_WIRE, make_range(template_node->range_left, 0)); + auto wnode = std::make_unique(AST_WIRE, make_range(template_node->range_left, 0)); wnode->str = name; wnode->is_logic = true; wnode->range_valid = true; @@ -547,24 +545,24 @@ static AstNode *make_packed_struct(AstNode *template_node, std::string &name, de // resolve packed dimension while (wnode->simplify(true, 1, -1, false)) {} // make sure this node is the one in scope for this name - current_scope[name] = wnode; + current_scope[name] = wnode.get(); // add all the struct members to scope under the wire's name add_members_to_scope(template_node, name); return wnode; } -static void prepend_ranges(AstNode *&range, AstNode *range_add) +static void prepend_ranges(std::unique_ptr &range, AstNode *range_add) { // Convert range to multirange. if (range->type == AST_RANGE) - range = new AstNode(AST_MULTIRANGE, range); + range = std::make_unique(AST_MULTIRANGE, std::move(range)); // Add range or ranges. if (range_add->type == AST_RANGE) range->children.insert(range->children.begin(), range_add->clone()); else { int i = 0; - for (auto child : range_add->children) + for (auto& child : range_add->children) range->children.insert(range->children.begin() + i++, child->clone()); } } @@ -575,16 +573,16 @@ static bool node_contains_assignment_to(const AstNode* node, const AstNode* var) if (node->type == AST_ASSIGN_EQ || node->type == AST_ASSIGN_LE) { // current node is iteslf an assignment log_assert(node->children.size() >= 2); - const AstNode* lhs = node->children[0]; + const AstNode* lhs = node->children[0].get(); if (lhs->type == AST_IDENTIFIER && lhs->str == var->str) return false; } - for (const AstNode* child : node->children) { + for (auto& child : node->children) { // if this child shadows the given variable - if (child != var && child->str == var->str && child->type == AST_WIRE) + if (child.get() != var && child->str == var->str && child->type == AST_WIRE) break; // skip the remainder of this block/scope // depth-first short circuit - if (!node_contains_assignment_to(child, var)) + if (!node_contains_assignment_to(child.get(), var)) return false; } return true; @@ -625,9 +623,9 @@ const RTLIL::Module* AstNode::lookup_cell_module() }; const AstNode *celltype = nullptr; - for (const AstNode *child : children) + for (auto& child : children) if (child->type == AST_CELLTYPE) { - celltype = child; + celltype = child.get(); break; } log_assert(celltype != nullptr); @@ -644,7 +642,7 @@ const RTLIL::Module* AstNode::lookup_cell_module() // build a mapping from true param name to param value size_t para_counter = 0; dict cell_params_map; - for (AstNode *child : children) { + for (auto& child : children) { if (child->type != AST_PARASET) continue; @@ -652,7 +650,7 @@ const RTLIL::Module* AstNode::lookup_cell_module() return nullptr; // let hierarchy handle this error IdString paraname = child->str.empty() ? module->avail_parameters[para_counter++] : child->str; - const AstNode *value = child->children[0]; + const AstNode *value = child->children[0].get(); if (value->type != AST_REALVALUE && value->type != AST_CONSTANT) return nullptr; // let genrtlil handle this error cell_params_map[paraname] = value->asParaConst(); @@ -684,8 +682,8 @@ static bool contains_unbased_unsized(const AstNode *node) { if (node->type == AST_CONSTANT) return node->is_unsized; - for (const AstNode *child : node->children) - if (contains_unbased_unsized(child)) + for (auto& child : node->children) + if (contains_unbased_unsized(child.get())) return true; return false; } @@ -694,19 +692,19 @@ static bool contains_unbased_unsized(const AstNode *node) // dimensions of the given wire reference void add_wire_for_ref(const RTLIL::Wire *ref, const std::string &str) { - AstNode *left = AstNode::mkconst_int(ref->width - 1 + ref->start_offset, true); - AstNode *right = AstNode::mkconst_int(ref->start_offset, true); + std::unique_ptr left = AstNode::mkconst_int(ref->width - 1 + ref->start_offset, true); + std::unique_ptr right = AstNode::mkconst_int(ref->start_offset, true); if (ref->upto) std::swap(left, right); - AstNode *range = new AstNode(AST_RANGE, left, right); + std::unique_ptr range = std::make_unique(AST_RANGE, std::move(left), std::move(right)); - AstNode *wire = new AstNode(AST_WIRE, range); + std::unique_ptr wire = std::make_unique(AST_WIRE, std::move(range)); wire->is_signed = ref->is_signed; wire->is_logic = true; wire->str = str; - current_ast_mod->children.push_back(wire); - current_scope[str] = wire; + current_scope[str] = wire.get(); + current_ast_mod->children.push_back(std::move(wire)); } enum class IdentUsage { @@ -733,10 +731,10 @@ static IdentUsage always_asgn_before_use(const AstNode *node, const std::string bool all_defined = true; bool any_used = false; bool has_default = false; - for (const AstNode *child : node->children) { + for (auto& child : node->children) { if (child->type == AST_COND && child->children.at(0)->type == AST_DEFAULT) has_default = true; - IdentUsage nested = always_asgn_before_use(child, target); + IdentUsage nested = always_asgn_before_use(child.get(), target); if (nested != IdentUsage::Assigned && child->type == AST_COND) all_defined = false; if (nested == IdentUsage::SyncRequired) @@ -753,20 +751,20 @@ static IdentUsage always_asgn_before_use(const AstNode *node, const std::string // Check if this is an assignment to the target variable. For simplicity, we // don't analyze sub-ranges of the variable. if (node->type == AST_ASSIGN_EQ) { - const AstNode *ident = node->children.at(0); + auto& ident = node->children.at(0); if (ident->type == AST_IDENTIFIER && ident->str == target) return IdentUsage::Assigned; } - for (const AstNode *child : node->children) { - IdentUsage nested = always_asgn_before_use(child, target); + for (auto& child : node->children) { + IdentUsage nested = always_asgn_before_use(child.get(), target); if (nested != IdentUsage::NotReferenced) return nested; } return IdentUsage::NotReferenced; } -AstNode *AstNode::clone_at_zero() +std::unique_ptr AstNode::clone_at_zero() { int width_hint; bool sign_hint; @@ -795,8 +793,7 @@ AstNode *AstNode::clone_at_zero() break; } - AstNode *that = new AstNode; - *that = *this; + auto that = clone(); for (auto &it : that->children) it = it->clone_at_zero(); for (auto &it : that->attributes) @@ -818,8 +815,8 @@ static bool try_determine_range_width(AstNode *range, int &result_width) return true; } - AstNode *left_at_zero_ast = range->children[0]->clone_at_zero(); - AstNode *right_at_zero_ast = range->children[1]->clone_at_zero(); + std::unique_ptr left_at_zero_ast = range->children[0]->clone_at_zero(); + std::unique_ptr right_at_zero_ast = range->children[1]->clone_at_zero(); while (left_at_zero_ast->simplify(true, 1, -1, false)) {} while (right_at_zero_ast->simplify(true, 1, -1, false)) {} @@ -831,8 +828,6 @@ static bool try_determine_range_width(AstNode *range, int &result_width) result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; } - delete left_at_zero_ast; - delete right_at_zero_ast; return ok; } @@ -891,13 +886,22 @@ static void check_auto_nosync(AstNode *node) // remove the attributes we've "consumed" for (const RTLIL::IdString &str : attrs_to_drop) { auto it = node->attributes.find(str); - delete it->second; node->attributes.erase(it); } // check local variables in any nested blocks - for (AstNode *child : node->children) - check_auto_nosync(child); + for (auto& child : node->children) + check_auto_nosync(child.get()); +} + +void AstNode::null_check() +{ + for (auto& child : children) { + // if (!child) + // VALGRIND_PRINTF_BACKTRACE("null child"); + log_assert((bool) child); + child->null_check(); + } } // convert the AST into a simpler AST that has all parameters substituted by their @@ -908,6 +912,7 @@ static void check_auto_nosync(AstNode *node) // nodes that link to a different node using names and lexical scoping. bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hint) { + // null_check(); static int recursion_counter = 0; static bool deep_recursion_warning = false; @@ -918,7 +923,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin static bool unevaluated_tern_branch = false; - AstNode *newNode = NULL; + std::unique_ptr newNode = nullptr; bool did_something = false; #if 0 @@ -926,7 +931,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, filename.c_str(), location.first_line, type2str(type).c_str(), this); log("const_fold=%d, stage=%d, width_hint=%d, sign_hint=%d\n", int(const_fold), int(stage), int(width_hint), int(sign_hint)); - // dumpAst(NULL, "> "); + // dumpAst(nullptr, "> "); #endif if (stage == 0) @@ -1006,7 +1011,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin std::swap(data_range_left, data_range_right); for (int i = 0; i < mem_size; i++) { - AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE, + auto reg = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true))); reg->str = stringf("%s[%d]", node->str.c_str(), i); reg->is_reg = true; @@ -1016,19 +1021,15 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin reg->set_attribute(it.first, it.second->clone()); reg->filename = node->filename; reg->location = node->location; - children.push_back(reg); while (reg->simplify(true, 1, -1, false)) { } + children.push_back(std::move(reg)); } } - AstNode *async_block = NULL; - while (mem2reg_as_needed_pass2(mem2reg_set, this, NULL, async_block)) { } + AstNode* async_block = nullptr; + while (mem2reg_as_needed_pass2(mem2reg_set, this, nullptr, async_block)) { } - vector delnodes; - mem2reg_remove(mem2reg_set, delnodes); - - for (auto node : delnodes) - delete node; + mem2reg_remove(mem2reg_set); } while (simplify(const_fold, 2, width_hint, sign_hint)) { } @@ -1055,8 +1056,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } if ((type == AST_TCALL) && - (str == "$display" || str == "$displayb" || str == "$displayh" || str == "$displayo" || - str == "$write" || str == "$writeb" || str == "$writeh" || str == "$writeo")) + (str == "$display" || str == "$displayb" || str == "$displayh" || str == "$displayo" || + str == "$write" || str == "$writeb" || str == "$writeh" || str == "$writeo")) { if (!current_always) { log_file_warning(filename, location.first_line, "System task `%s' outside initial or always block is unsupported.\n", str.c_str()); @@ -1064,7 +1065,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin str = std::string(); } else { // simplify the expressions and convert them to a special cell later in genrtlil - for (auto node : children) + for (auto& node : children) while (node->simplify(true, stage, -1, false)) {} if (current_always->type == AST_INITIAL && !flag_nodisplay && stage == 2) { @@ -1104,16 +1105,13 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin label_genblks(existing, counter); std::map this_wire_scope; for (size_t i = 0; i < children.size(); i++) { - AstNode *node = children[i]; + AstNode* node = children[i].get(); if (node->type == AST_WIRE) { if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { - for (auto c : node->children[0]->children) { - if (!c->is_simple_const_expr()) { - if (attributes.count(ID::dynports)) - delete attributes.at(ID::dynports); + for (auto& c : node->children[0]->children) { + if (!c->is_simple_const_expr()) set_attribute(ID::dynports, AstNode::mkconst_int(1, true)); - } } } if (this_wire_scope.count(node->str) > 0) { @@ -1123,16 +1121,15 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (!node->is_input && !node->is_output && node->is_reg && node->children.size() == 0) goto wires_are_compatible; if (first_node->children.size() == 0 && node->children.size() == 1 && node->children[0]->type == AST_RANGE) { - AstNode *r = node->children[0]; + AstNode* r = node->children[0].get(); if (r->range_valid && r->range_left == 0 && r->range_right == 0) { - delete r; node->children.pop_back(); } } if (first_node->children.size() != node->children.size()) goto wires_are_incompatible; for (size_t j = 0; j < node->children.size(); j++) { - AstNode *n1 = first_node->children[j], *n2 = node->children[j]; + auto &n1 = first_node->children[j], &n2 = node->children[j]; if (n1->type == AST_RANGE && n2->type == AST_RANGE && n1->range_valid && n2->range_valid) { if (n1->range_left != n2->range_left) goto wires_are_incompatible; @@ -1159,13 +1156,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (node->is_signed) first_node->is_signed = true; for (auto &it : node->attributes) { - if (first_node->attributes.count(it.first) > 0) - delete first_node->attributes[it.first]; first_node->set_attribute(it.first, it.second->clone()); } children.erase(children.begin()+(i--)); did_something = true; - delete node; continue; wires_are_incompatible: if (stage > 1) @@ -1183,22 +1177,22 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } if (node->type == AST_ENUM) { current_scope[node->str] = node; - for (auto enode : node->children) { + for (auto& enode : node->children) { log_assert(enode->type==AST_ENUM_ITEM); if (current_scope.count(enode->str) == 0) - current_scope[enode->str] = enode; + current_scope[enode->str] = enode.get(); else input_error("enum item %s already exists\n", enode->str.c_str()); } } } for (size_t i = 0; i < children.size(); i++) { - AstNode *node = children[i]; + auto& node = children[i]; if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF) while (node->simplify(true, 1, -1, false)) did_something = true; if (node->type == AST_ENUM) { - for (auto enode : node->children){ + for (auto& enode : node->children){ log_assert(enode->type==AST_ENUM_ITEM); while (node->simplify(true, 1, -1, false)) did_something = true; @@ -1206,27 +1200,27 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } } - for (AstNode *child : children) + for (auto& child : children) if (child->type == AST_ALWAYS && child->attributes.count(ID::always_comb)) - check_auto_nosync(child); + check_auto_nosync(child.get()); } // create name resolution entries for all objects with names if (type == AST_PACKAGE) { //add names to package scope for (size_t i = 0; i < children.size(); i++) { - AstNode *node = children[i]; + auto& node = children[i]; // these nodes appear at the top level in a package and can define names if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_TYPEDEF || node->type == AST_FUNCTION || node->type == AST_TASK) { - current_scope[node->str] = node; + current_scope[node->str] = node.get(); } if (node->type == AST_ENUM) { - current_scope[node->str] = node; - for (auto enode : node->children) { + current_scope[node->str] = node.get(); + for (auto& enode : node->children) { log_assert(enode->type==AST_ENUM_ITEM); if (current_scope.count(enode->str) == 0) - current_scope[enode->str] = enode; + current_scope[enode->str] = enode.get(); else input_error("enum item %s already exists in package\n", enode->str.c_str()); } @@ -1250,7 +1244,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin current_always_clocked = false; if (type == AST_ALWAYS) - for (auto child : children) { + for (auto& child : children) { if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) current_always_clocked = true; if (child->type == AST_EDGE && GetSize(child->children) == 1 && @@ -1262,7 +1256,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (type == AST_CELL) { bool lookup_suggested = false; - for (AstNode *child : children) { + for (auto& child : children) { // simplify any parameters to constants if (child->type == AST_PARASET) while (child->simplify(true, 1, -1, false)) { } @@ -1272,7 +1266,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (child->type == AST_ARGUMENT) { if (child->children.size() != 1) continue; - const AstNode *value = child->children[0]; + const auto& value = child->children[0]; if (value->type == AST_IDENTIFIER) { const AstNode *elem = value->id2ast; if (elem == nullptr) { @@ -1289,7 +1283,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // to be indirected to produce an unsigned connection lookup_suggested = true; } - else if (contains_unbased_unsized(value)) + else if (contains_unbased_unsized(value.get())) // unbased unsized literals extend to width of the context lookup_suggested = true; } @@ -1300,7 +1294,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin module = lookup_cell_module(); if (module) { size_t port_counter = 0; - for (AstNode *child : children) { + for (auto& child : children) { if (child->type != AST_ARGUMENT) continue; @@ -1324,17 +1318,21 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin log_assert(child->children.size() <= 1); if (child->children.empty()) continue; - AstNode *arg = child->children[0]; - // plain identifiers never need indirection; this also prevents - // adding infinite levels of indirection - if (arg->type == AST_IDENTIFIER && arg->children.empty()) - continue; + { + auto arg_check = child->children[0].get(); - // only add indirection for standard inputs or outputs - if (ref->port_input == ref->port_output) - continue; + // plain identifiers never need indirection; this also prevents + // adding infinite levels of indirection + if (arg_check->type == AST_IDENTIFIER && arg_check->children.empty()) + continue; + // only add indirection for standard inputs or outputs + if (ref->port_input == ref->port_output) + continue; + } + + auto arg = std::move(child->children[0]); did_something = true; // create the indirection wire @@ -1343,20 +1341,21 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin std::string tmp_str = sstr.str(); add_wire_for_ref(ref, tmp_str); - AstNode *asgn = new AstNode(AST_ASSIGN); - current_ast_mod->children.push_back(asgn); + auto asgn_owned = std::make_unique(AST_ASSIGN); + auto* asgn = asgn_owned.get(); + current_ast_mod->children.push_back(std::move(asgn_owned)); - AstNode *ident = new AstNode(AST_IDENTIFIER); + auto ident = std::make_unique(AST_IDENTIFIER); ident->str = tmp_str; child->children[0] = ident->clone(); if (ref->port_input && !ref->port_output) { - asgn->children.push_back(ident); - asgn->children.push_back(arg); + asgn->children.push_back(std::move(ident)); + asgn->children.push_back(std::move(arg)); } else { log_assert(!ref->port_input && ref->port_output); - asgn->children.push_back(arg); - asgn->children.push_back(ident); + asgn->children.push_back(std::move(arg)); + asgn->children.push_back(std::move(ident)); } asgn->fixup_hierarchy_flags(); } @@ -1416,7 +1415,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin case AST_STRUCT: case AST_UNION: if (!basic_prep) { - for (auto *node : children) { + for (auto& node : children) { // resolve any ranges while (!node->basic_prep && node->simplify(true, stage, -1, false)) { did_something = true; @@ -1430,7 +1429,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // instance so add a wire for the packed structure auto wnode = make_packed_struct(this, str, attributes); log_assert(current_ast_mod); - current_ast_mod->children.push_back(wnode); + current_ast_mod->children.push_back(std::move(wnode)); } basic_prep = true; } @@ -1455,7 +1454,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin case AST_ENUM: //log("\nENUM %s: %d child %d\n", str.c_str(), basic_prep, children[0]->basic_prep); if (!basic_prep) { - for (auto item_node : children) { + for (auto& item_node : children) { while (!item_node->basic_prep && item_node->simplify(false, stage, -1, false)) did_something = true; } @@ -1472,8 +1471,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin auto item_node = current_scope[children[0]->str]; if (item_node->type == AST_STRUCT || item_node->type == AST_UNION) { set_attribute(ID::wiretype, item_node->clone()); - size_packed_struct(attributes[ID::wiretype], 0); - add_members_to_scope(attributes[ID::wiretype], str); + size_packed_struct(attributes[ID::wiretype].get(), 0); + add_members_to_scope(attributes[ID::wiretype].get(), str); } } while (!children[0]->basic_prep && children[0]->simplify(false, stage, -1, false) == true) @@ -1501,11 +1500,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin break; case AST_CAST_SIZE: { - int width = 1; - AstNode *node; - AstNode *child = children[0]; - - if (child->type == AST_WIRE) { + if (children[0]->type == AST_WIRE) { + int width = 1; + std::unique_ptr node; + AstNode* child = children[0].release(); if (child->children.size() == 0) { // Base type (e.g., int) width = child->range_left - child->range_right +1; @@ -1521,7 +1519,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (resolved_type_node->type != AST_TYPEDEF) input_error("`%s' does not name a type\n", type_name.c_str()); log_assert(resolved_type_node->children.size() == 1); - AstNode *template_node = resolved_type_node->children[0]; + AstNode *template_node = resolved_type_node->children[0].get(); // Ensure typedef itself is fully simplified while (template_node->simplify(const_fold, stage, width_hint, sign_hint)) {}; @@ -1530,7 +1528,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin { case AST_WIRE: { if (template_node->children.size() > 0 && template_node->children[0]->type == AST_RANGE) - width = range_width(this, template_node->children[0]); + width = range_width(this, template_node->children[0].get()); child->delete_children(); node = mkconst_int(width, true); break; @@ -1549,9 +1547,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } } - delete child; children.erase(children.begin()); - children.insert(children.begin(), node); + children.insert(children.begin(), std::move(node)); } detect_width_simple = true; @@ -1608,7 +1605,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin case AST_GT: width_hint = -1; sign_hint = true; - for (auto child : children) { + for (auto& child : children) { while (!child->basic_prep && child->simplify(false, stage, -1, false) == true) did_something = true; child->detectSignWidthWorker(width_hint, sign_hint); @@ -1646,7 +1643,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (type == AST_REPLICATE) while (children[0]->simplify(true, stage, -1, false) == true) did_something = true; - for (auto child : children) + for (auto& child : children) while (!child->basic_prep && child->simplify(false, stage, -1, false) == true) did_something = true; detectSignWidth(width_hint, sign_hint); @@ -1663,11 +1660,11 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin bool backup_unevaluated_tern_branch = unevaluated_tern_branch; AstNode *chosen = get_tern_choice().first; - unevaluated_tern_branch = backup_unevaluated_tern_branch || chosen == children[2]; + unevaluated_tern_branch = backup_unevaluated_tern_branch || chosen == children[2].get(); while (!children[1]->basic_prep && children[1]->simplify(false, stage, -1, false)) did_something = true; - unevaluated_tern_branch = backup_unevaluated_tern_branch || chosen == children[1]; + unevaluated_tern_branch = backup_unevaluated_tern_branch || chosen == children[1].get(); while (!children[2]->basic_prep && children[2]->simplify(false, stage, -1, false)) did_something = true; @@ -1704,12 +1701,12 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (children[0]->type == AST_CONSTANT && children[0]->bits_only_01()) { children[0]->is_signed = sign_hint; RTLIL::Const case_expr = children[0]->bitsAsConst(width_hint, sign_hint); - std::vector new_children; - new_children.push_back(children[0]); + std::vector> new_children; + new_children.push_back(std::move(children[0])); for (int i = 1; i < GetSize(children); i++) { - AstNode *child = children[i]; + auto& child = children[i]; log_assert(child->type == AST_COND || child->type == AST_CONDX || child->type == AST_CONDZ); - for (auto v : child->children) { + for (auto& v : child->children) { if (v->type == AST_DEFAULT) goto keep_const_cond; if (v->type == AST_BLOCK) @@ -1720,8 +1717,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin RTLIL::Const match = const_eq(case_expr, case_item_expr, sign_hint, sign_hint, 1); log_assert(match.size() == 1); if (match.front() == RTLIL::State::S1) { - while (i+1 < GetSize(children)) - delete children[++i]; + // This is the only reachable case. Skip to the end + i = GetSize(children); goto keep_const_cond; } continue; @@ -1730,9 +1727,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } if (0) keep_const_cond: - new_children.push_back(child); - else - delete child; + new_children.push_back(std::move(child)); } new_children.swap(children); } @@ -1768,7 +1763,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin flag_autowire = true; if (type == AST_TERNARY && i > 0 && !unevaluated_tern_branch) { AstNode *chosen = get_tern_choice().first; - unevaluated_tern_branch = chosen && chosen != children[i]; + unevaluated_tern_branch = chosen && chosen != children[i].get(); } while (did_something_here && i < children.size()) { bool const_fold_here = const_fold; @@ -1780,10 +1775,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin const_fold_here = true; if (type == AST_BLOCK) { current_block = this; - current_block_child = children[i]; + current_block_child = children[i].get(); } if ((type == AST_ALWAYS || type == AST_INITIAL) && children[i]->type == AST_BLOCK) - current_top_block = children[i]; + current_top_block = children[i].get(); if (i == 0 && child_0_is_self_determined) width_hint_here = -1, sign_hint_here = false; if (i == 1 && child_1_is_self_determined) @@ -1797,7 +1792,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin did_something = true; } if (stage == 2 && children[i]->type == AST_INITIAL && current_ast_mod != this) { - current_ast_mod->children.push_back(children[i]); + current_ast_mod->children.push_back(std::move(children[i])); children.erase(children.begin() + (i--)); did_something = true; } @@ -1837,7 +1832,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin current_always_clocked = backup_current_always_clocked; for (auto it = backup_scope.begin(); it != backup_scope.end(); it++) { - if (it->second == NULL) + if (it->second == nullptr) current_scope.erase(it->first); else current_scope[it->first] = it->second; @@ -1877,18 +1872,18 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin input_error("Defparam argument `%s . %s` does not match a cell!\n", RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); - AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL); + auto paraset = std::make_unique(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : nullptr); paraset->str = paramname; AstNode *cell = current_scope.at(modname); - cell->children.insert(cell->children.begin() + 1, paraset); + cell->children.insert(cell->children.begin() + 1, std::move(paraset)); delete_children(); } // resolve typedefs if (type == AST_TYPEDEF) { log_assert(children.size() == 1); - auto type_node = children[0]; + auto& type_node = children[0]; log_assert(type_node->type == AST_WIRE || type_node->type == AST_MEMORY || type_node->type == AST_STRUCT || type_node->type == AST_UNION); while (type_node->simplify(const_fold, stage, width_hint, sign_hint)) { did_something = true; @@ -1909,7 +1904,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (resolved_type_node->type != AST_TYPEDEF) input_error("`%s' does not name a type\n", type_name.c_str()); log_assert(resolved_type_node->children.size() == 1); - AstNode *template_node = resolved_type_node->children[0]; + auto& template_node = resolved_type_node->children[0]; // Resolve the typedef from the bottom up, recursing within the current // block of code. Defer further simplification until the complete type is @@ -1918,9 +1913,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (!str.empty() && str[0] == '\\' && (template_node->type == AST_STRUCT || template_node->type == AST_UNION)) { // replace instance with wire representing the packed structure - newNode = make_packed_struct(template_node, str, attributes); - if (newNode->attributes.count(ID::wiretype)) - delete newNode->attributes[ID::wiretype]; + newNode = make_packed_struct(template_node.get(), str, attributes); newNode->set_attribute(ID::wiretype, mkconst_str(resolved_type_node->str)); // add original input/output attribute to resolved wire newNode->is_input = this->is_input; @@ -1943,7 +1936,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin newNode->set_attribute(pair.first, pair.second->clone()); // if an enum then add attributes to support simulator tracing - newNode->annotateTypedEnums(template_node); + newNode->annotateTypedEnums(template_node.get()); bool add_packed_dimensions = (type == AST_WIRE && GetSize(children) > 1) || (type == AST_MEMORY && GetSize(children) > 2); @@ -1953,20 +1946,20 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // Add packed dimensions. if (add_packed_dimensions) { - AstNode *packed = children[1]; + auto& packed = children[1]; if (newNode->children.empty()) newNode->children.insert(newNode->children.begin(), packed->clone()); else - prepend_ranges(newNode->children[0], packed); + prepend_ranges(newNode->children[0], packed.get()); } // Add unpacked dimensions. if (type == AST_MEMORY) { - AstNode *unpacked = children.back(); + auto& unpacked = children.back(); if (GetSize(newNode->children) < 2) newNode->children.push_back(unpacked->clone()); else - prepend_ranges(newNode->children[1], unpacked); + prepend_ranges(newNode->children[1], unpacked.get()); newNode->type = type; } @@ -1987,11 +1980,11 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // Pretend it's just a wire in order to resolve the type in the code block above. AstNodeType param_type = type; type = AST_WIRE; - AstNode *expr = children[0]; + std::unique_ptr expr = std::move(children.front()); children.erase(children.begin()); while (is_custom_type && simplify(const_fold, stage, width_hint, sign_hint)) {}; type = param_type; - children.insert(children.begin(), expr); + children.insert(children.begin(), std::move(expr)); if (children[1]->type == AST_MEMORY) input_error("unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str()); @@ -2004,7 +1997,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // resolve constant prefixes if (type == AST_PREFIX) { if (children[0]->type != AST_CONSTANT) { - // dumpAst(NULL, "> "); + // dumpAst(nullptr, "> "); input_error("Index in generate block prefix syntax is not constant!\n"); } if (children[1]->type == AST_PREFIX) @@ -2069,13 +2062,13 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin range_right = children[0]->range_right; bool force_upto = false, force_downto = false; if (attributes.count(ID::force_upto)) { - AstNode *val = attributes[ID::force_upto]; + AstNode *val = attributes[ID::force_upto].get(); if (val->type != AST_CONSTANT) input_error("Attribute `force_upto' with non-constant value!\n"); force_upto = val->asAttrConst().as_bool(); } if (attributes.count(ID::force_downto)) { - AstNode *val = attributes[ID::force_downto]; + AstNode *val = attributes[ID::force_downto].get(); if (val->type != AST_CONSTANT) input_error("Attribute `force_downto' with non-constant value!\n"); force_downto = val->asAttrConst().as_bool(); @@ -2110,19 +2103,18 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin for (int i = std::min(GetSize(children), 2) - 1; i >= 0; i--) { if (children[i]->type == AST_MULTIRANGE) { int width = 1; - for (auto range : children[i]->children) { - width *= add_dimension(this, range); + for (auto& range : children[i]->children) { + width *= add_dimension(this, range.get()); if (i) unpacked_dimensions++; } - delete children[i]; int left = width - 1, right = 0; if (i) std::swap(left, right); - children[i] = new AstNode(AST_RANGE, mkconst_int(left, true), mkconst_int(right, true)); + children[i] = std::make_unique(AST_RANGE, mkconst_int(left, true), mkconst_int(right, true)); fixup_hierarchy_flags(); did_something = true; } else if (children[i]->type == AST_RANGE) { - add_dimension(this, children[i]); + add_dimension(this, children[i].get()); if (i) unpacked_dimensions++; } } @@ -2134,15 +2126,15 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // Resolve multidimensional array access. if (type == AST_IDENTIFIER && !basic_prep && id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_MEMORY) && - children.size() > 0 && (children[0]->type == AST_RANGE || children[0]->type == AST_MULTIRANGE)) + children.size() > 0 && (children[0]->type == AST_RANGE || children[0]->type == AST_MULTIRANGE)) { int dims_sel = children[0]->type == AST_MULTIRANGE ? children[0]->children.size() : 1; // Save original number of dimensions for $size() etc. integer = dims_sel; // Split access into unpacked and packed parts. - AstNode *unpacked_range = nullptr; - AstNode *packed_range = nullptr; + std::unique_ptr unpacked_range = nullptr; + std::unique_ptr packed_range = nullptr; if (id2ast->unpacked_dimensions) { if (id2ast->unpacked_dimensions > 1) { @@ -2150,8 +2142,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin unpacked_range = make_index_range(id2ast, true); } else { // Index into one-dimensional unpacked part; unlink simple range node. - AstNode *&range = children[0]->type == AST_MULTIRANGE ? children[0]->children[0] : children[0]; - unpacked_range = range; + auto& range = children[0]->type == AST_MULTIRANGE ? children[0]->children[0] : children[0]; + unpacked_range = std::move(range); range = nullptr; } } @@ -2162,21 +2154,19 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin packed_range = make_index_range(id2ast, false); } else { // Index into one-dimensional packed part; unlink simple range node. - AstNode *&range = children[0]->type == AST_MULTIRANGE ? children[0]->children[dims_sel - 1] : children[0]; - packed_range = range; + auto& range = children[0]->type == AST_MULTIRANGE ? children[0]->children[dims_sel - 1] : children[0]; + packed_range = std::move(range); range = nullptr; } } - for (auto &it : children) - delete it; children.clear(); if (unpacked_range) - children.push_back(unpacked_range); + children.push_back(std::move(unpacked_range)); if (packed_range) - children.push_back(packed_range); + children.push_back(std::move(packed_range)); fixup_hierarchy_flags(); basic_prep = true; @@ -2193,7 +2183,6 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin RTLIL::Const constvalue = children[0]->realAsConst(width); log_file_warning(filename, location.first_line, "converting real value %e to binary %s.\n", children[0]->realvalue, log_signal(constvalue)); - delete children[0]; children[0] = mkconst_bits(constvalue.to_bits(), sign_hint); fixup_hierarchy_flags(); did_something = true; @@ -2202,9 +2191,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (width != int(children[0]->bits.size())) { RTLIL::SigSpec sig(children[0]->bits); sig.extend_u0(width, children[0]->is_signed); - AstNode *old_child_0 = children[0]; children[0] = mkconst_bits(sig.as_const().to_bits(), is_signed); - delete old_child_0; fixup_hierarchy_flags(); } children[0]->is_signed = is_signed; @@ -2216,8 +2203,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } else if (children.size() > 1 && children[1]->type == AST_REALVALUE && children[0]->type == AST_CONSTANT) { double as_realvalue = children[0]->asReal(sign_hint); - delete children[0]; - children[0] = new AstNode(AST_REALVALUE); + children[0] = std::make_unique(AST_REALVALUE); children[0]->realvalue = as_realvalue; fixup_hierarchy_flags(); did_something = true; @@ -2246,7 +2232,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (found_sname) { // structure member, rewrite this node to reference the packed struct wire auto range = make_index_range(item_node); - newNode = new AstNode(AST_IDENTIFIER, range); + newNode = std::make_unique(AST_IDENTIFIER, std::move(range)); newNode->str = sname; // save type and original number of dimensions for $size() etc. newNode->set_attribute(ID::wiretype, item_node->clone()); @@ -2258,7 +2244,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } newNode->basic_prep = true; if (item_node->is_signed) - newNode = new AstNode(AST_TO_SIGNED, newNode); + newNode = std::make_unique(AST_TO_SIGNED, std::move(newNode)); goto apply_newNode; } } @@ -2269,7 +2255,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (current_scope.count(str) == 0) { AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod; str = try_pop_module_prefix(); - for (auto node : current_scope_ast->children) { + for (auto& node : current_scope_ast->children) { //log("looking at mod scope child %s\n", type2str(node->type).c_str()); switch (node->type) { case AST_PARAMETER: @@ -2284,16 +2270,16 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str()); if (str == node->str) { //log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str()); - current_scope[node->str] = node; + current_scope[node->str] = node.get(); } break; case AST_ENUM: - current_scope[node->str] = node; - for (auto enum_node : node->children) { + current_scope[node->str] = node.get(); + for (auto& enum_node : node->children) { log_assert(enum_node->type==AST_ENUM_ITEM); if (str == enum_node->str) { //log("\nadding enum item %s to scope\n", str.c_str()); - current_scope[str] = enum_node; + current_scope[str] = enum_node.get(); } } break; @@ -2306,10 +2292,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (current_ast_mod == nullptr) { input_error("Identifier `%s' is implicitly declared outside of a module.\n", str.c_str()); } else if (flag_autowire || str == "\\$global_clock") { - AstNode *auto_wire = new AstNode(AST_AUTOWIRE); + auto auto_wire = std::make_unique(AST_AUTOWIRE); auto_wire->str = str; - current_ast_mod->children.push_back(auto_wire); - current_scope[str] = auto_wire; + current_scope[str] = auto_wire.get(); + current_ast_mod->children.push_back(std::move(auto_wire)); did_something = true; } else { input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str()); @@ -2324,7 +2310,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // split memory access with bit select to individual statements if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue && stage == 2) { - if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1) + if (id2ast == nullptr || id2ast->type != AST_MEMORY || children[0]->children.size() != 1) input_error("Invalid bit-select on memory access!\n"); int mem_width, mem_size, addr_bits; @@ -2340,38 +2326,38 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin sstr << "$mem2bits$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++); std::string wire_id = sstr.str(); - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true))); + auto wire_owned = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true))); + auto* wire = wire_owned.get(); + current_ast_mod->children.push_back(std::move(wire_owned)); wire->str = wire_id; if (current_block) wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); - current_ast_mod->children.push_back(wire); while (wire->simplify(true, 1, -1, false)) { } - AstNode *data = clone(); - delete data->children[1]; + auto data = clone(); data->children.pop_back(); - AstNode *assign = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), data); + auto assign = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), std::move(data)); assign->children[0]->str = wire_id; assign->children[0]->was_checked = true; if (current_block) { size_t assign_idx = 0; - while (assign_idx < current_block->children.size() && current_block->children[assign_idx] != current_block_child) + while (assign_idx < current_block->children.size() && current_block->children[assign_idx].get() != current_block_child) assign_idx++; log_assert(assign_idx < current_block->children.size()); - current_block->children.insert(current_block->children.begin()+assign_idx, assign); + current_block->children.insert(current_block->children.begin()+assign_idx, std::move(assign)); wire->is_reg = true; } else { - AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK)); - proc->children[0]->children.push_back(assign); - current_ast_mod->children.push_back(proc); + auto proc = std::make_unique(AST_ALWAYS, std::make_unique(AST_BLOCK)); + proc->children[0]->children.push_back(std::move(assign)); + current_ast_mod->children.push_back(std::move(proc)); } - newNode = new AstNode(AST_IDENTIFIER, children[1]->clone()); + newNode = std::make_unique(AST_IDENTIFIER, children[1]->clone()); newNode->str = wire_id; newNode->integer = integer; // save original number of dimensions for $size() etc. newNode->id2ast = wire; @@ -2383,8 +2369,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (type == AST_REPEAT) { - AstNode *count = children[0]; - AstNode *body = children[1]; + auto count = std::move(children[0]); + auto body = std::move(children[1]); // eval count expression while (count->simplify(true, stage, 32, true)) { } @@ -2398,22 +2384,20 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin for (int i = 0; i < count->bitsAsConst().as_int(); i++) children.insert(children.begin(), body->clone()); - delete count; - delete body; did_something = true; } // unroll for loops and generate-for blocks if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0) { - AstNode *init_ast = children[0]; - AstNode *while_ast = children[1]; - AstNode *next_ast = children[2]; - AstNode *body_ast = children[3]; + auto& init_ast = children[0]; + auto& while_ast = children[1]; + auto& next_ast = children[2]; + auto* body_ast = children[3].get(); while (body_ast->type == AST_GENBLOCK && body_ast->str.empty() && body_ast->children.size() == 1 && body_ast->children.at(0)->type == AST_GENBLOCK) - body_ast = body_ast->children.at(0); + body_ast = body_ast->children.at(0).get(); const char* loop_type_str = "procedural"; const char* var_type_str = "register"; @@ -2429,16 +2413,16 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (next_ast->type != AST_ASSIGN_EQ) input_error("Unsupported 3rd expression of %s for-loop!\n", loop_type_str); - if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != var_type) + if (init_ast->children[0]->id2ast == nullptr || init_ast->children[0]->id2ast->type != var_type) input_error("Left hand side of 1st expression of %s for-loop is not a %s!\n", loop_type_str, var_type_str); - if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != var_type) + if (next_ast->children[0]->id2ast == nullptr || next_ast->children[0]->id2ast->type != var_type) input_error("Left hand side of 3rd expression of %s for-loop is not a %s!\n", loop_type_str, var_type_str); if (init_ast->children[0]->id2ast != next_ast->children[0]->id2ast) input_error("Incompatible left-hand sides in 1st and 3rd expression of %s for-loop!\n", loop_type_str); // eval 1st expression - AstNode *varbuf = init_ast->children[1]->clone(); + auto varbuf = init_ast->children[1]->clone(); { int expr_width_hint = -1; bool expr_sign_hint = true; @@ -2463,23 +2447,23 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } } - varbuf = new AstNode(AST_LOCALPARAM, varbuf); + varbuf = std::make_unique(AST_LOCALPARAM, std::move(varbuf)); varbuf->str = init_ast->children[0]->str; AstNode *backup_scope_varbuf = current_scope[varbuf->str]; - current_scope[varbuf->str] = varbuf; + current_scope[varbuf->str] = varbuf.get(); size_t current_block_idx = 0; if (type == AST_FOR) { while (current_block_idx < current_block->children.size() && - current_block->children[current_block_idx] != current_block_child) + current_block->children[current_block_idx].get() != current_block_child) current_block_idx++; } while (1) { // eval 2nd expression - AstNode *buf = while_ast->clone(); + auto buf = while_ast->clone(); { int expr_width_hint = -1; bool expr_sign_hint = true; @@ -2491,10 +2475,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin input_error("2nd expression of %s for-loop is not constant!\n", loop_type_str); if (buf->integer == 0) { - delete buf; break; } - delete buf; // expand body int index = varbuf->children[0]->integer; @@ -2507,27 +2489,26 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin std::string prefix = sstr.str(); // create a scoped localparam for the current value of the loop variable - AstNode *local_index = varbuf->clone(); + auto local_index = varbuf->clone(); size_t pos = local_index->str.rfind('.'); if (pos != std::string::npos) // remove outer prefix local_index->str = "\\" + local_index->str.substr(pos + 1); local_index->str = prefix_id(prefix, local_index->str); - current_scope[local_index->str] = local_index; - current_ast_mod->children.push_back(local_index); + current_scope[local_index->str] = local_index.get(); + current_ast_mod->children.push_back(std::move(local_index)); buf->expand_genblock(prefix); if (type == AST_GENFOR) { for (size_t i = 0; i < buf->children.size(); i++) { buf->children[i]->simplify(const_fold, stage, -1, false); - current_ast_mod->children.push_back(buf->children[i]); + current_ast_mod->children.push_back(std::move(buf->children[i])); } } else { for (size_t i = 0; i < buf->children.size(); i++) - current_block->children.insert(current_block->children.begin() + current_block_idx++, buf->children[i]); + current_block->children.insert(current_block->children.begin() + current_block_idx++, std::move(buf->children[i])); } buf->children.clear(); - delete buf; // eval 3rd expression buf = next_ast->children[1]->clone(); @@ -2542,19 +2523,16 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (buf->type != AST_CONSTANT) input_error("Right hand side of 3rd expression of %s for-loop is not constant (%s)!\n", loop_type_str, type2str(buf->type).c_str()); - delete varbuf->children[0]; - varbuf->children[0] = buf; + varbuf->children[0] = std::move(buf); } if (type == AST_FOR) { - AstNode *buf = next_ast->clone(); - delete buf->children[1]; + auto buf = next_ast->clone(); buf->children[1] = varbuf->children[0]->clone(); - current_block->children.insert(current_block->children.begin() + current_block_idx++, buf); + current_block->children.insert(current_block->children.begin() + current_block_idx++, std::move(buf)); } current_scope[varbuf->str] = backup_scope_varbuf; - delete varbuf; delete_children(); did_something = true; } @@ -2580,19 +2558,19 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin && is_autonamed_block(str)) // track local variables in this block so we can consider adding // nosync once the block has been fully elaborated - for (AstNode *child : children) + for (auto& child : children) if (child->type == AST_WIRE && !child->attributes.count(ID::nosync)) - mark_auto_nosync(this, child); + mark_auto_nosync(this, child.get()); - std::vector new_children; + std::vector> new_children; for (size_t i = 0; i < children.size(); i++) if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) { children[i]->simplify(false, stage, -1, false); - current_ast_mod->children.push_back(children[i]); - current_scope[children[i]->str] = children[i]; + current_scope[children[i]->str] = children[i].get(); + current_ast_mod->children.push_back(std::move(children[i])); } else - new_children.push_back(children[i]); + new_children.push_back(std::move(children[i])); children.swap(new_children); did_something = true; @@ -2608,7 +2586,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin for (size_t i = 0; i < children.size(); i++) { children[i]->simplify(const_fold, stage, -1, false); - current_ast_mod->children.push_back(children[i]); + current_ast_mod->children.push_back(std::move(children[i])); } children.clear(); @@ -2618,7 +2596,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // simplify generate-if blocks if (type == AST_GENIF && children.size() != 0) { - AstNode *buf = children[0]->clone(); + auto buf = children[0]->clone(); while (buf->simplify(true, stage, width_hint, sign_hint)) { } if (buf->type != AST_CONSTANT) { // for (auto f : log_files) @@ -2626,17 +2604,15 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin input_error("Condition for generate if is not constant!\n"); } if (buf->asBool() != 0) { - delete buf; buf = children[1]->clone(); } else { - delete buf; - buf = children.size() > 2 ? children[2]->clone() : NULL; + buf = children.size() > 2 ? children[2]->clone() : nullptr; } if (buf) { if (buf->type != AST_GENBLOCK) - buf = new AstNode(AST_GENBLOCK, buf); + buf = std::make_unique(AST_GENBLOCK, std::move(buf)); if (!buf->str.empty()) { buf->expand_genblock(buf->str + "."); @@ -2644,11 +2620,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin for (size_t i = 0; i < buf->children.size(); i++) { buf->children[i]->simplify(const_fold, stage, -1, false); - current_ast_mod->children.push_back(buf->children[i]); + current_ast_mod->children.push_back(std::move(buf->children[i])); } buf->children.clear(); - delete buf; } delete_children(); @@ -2658,7 +2633,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // simplify generate-case blocks if (type == AST_GENCASE && children.size() != 0) { - AstNode *buf = children[0]->clone(); + auto buf = children[0]->clone(); while (buf->simplify(true, stage, width_hint, sign_hint)) { } if (buf->type != AST_CONSTANT) { // for (auto f : log_files) @@ -2668,24 +2643,23 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin bool ref_signed = buf->is_signed; RTLIL::Const ref_value = buf->bitsAsConst(); - delete buf; - AstNode *selected_case = NULL; + AstNode *selected_case = nullptr; for (size_t i = 1; i < children.size(); i++) { log_assert(children.at(i)->type == AST_COND || children.at(i)->type == AST_CONDX || children.at(i)->type == AST_CONDZ); - AstNode *this_genblock = NULL; - for (auto child : children.at(i)->children) { - log_assert(this_genblock == NULL); + AstNode *this_genblock = nullptr; + for (auto& child : children.at(i)->children) { + log_assert(this_genblock == nullptr); if (child->type == AST_GENBLOCK) - this_genblock = child; + this_genblock = child.get(); } - for (auto child : children.at(i)->children) + for (auto& child : children.at(i)->children) { if (child->type == AST_DEFAULT) { - if (selected_case == NULL) + if (selected_case == nullptr) selected_case = this_genblock; continue; } @@ -2702,7 +2676,6 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } bool is_selected = RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool(); - delete buf; if (is_selected) { selected_case = this_genblock; @@ -2712,7 +2685,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } } - if (selected_case != NULL) + if (selected_case != nullptr) { log_assert(selected_case->type == AST_GENBLOCK); buf = selected_case->clone(); @@ -2723,11 +2696,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin for (size_t i = 0; i < buf->children.size(); i++) { buf->children[i]->simplify(const_fold, stage, -1, false); - current_ast_mod->children.push_back(buf->children[i]); + current_ast_mod->children.push_back(std::move(buf->children[i])); } buf->children.clear(); - delete buf; } delete_children(); @@ -2740,13 +2712,14 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (!children.at(0)->range_valid) input_error("Non-constant array range on cell array.\n"); - newNode = new AstNode(AST_GENBLOCK); + newNode = std::make_unique(AST_GENBLOCK); int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1; for (int i = 0; i < num; i++) { int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i; - AstNode *new_cell = children.at(1)->clone(); - newNode->children.push_back(new_cell); + auto new_cell_owned = children.at(1)->clone(); + auto* new_cell = new_cell_owned.get(); + newNode->children.push_back(std::move(new_cell_owned)); new_cell->str += stringf("[%d]", idx); if (new_cell->type == AST_PRIMITIVE) { input_error("Cell arrays of primitives are currently not supported.\n"); @@ -2765,13 +2738,12 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (children.size() < 2) input_error("Insufficient number of arguments for primitive `%s'!\n", str.c_str()); - std::vector children_list; - for (auto child : children) { + std::vector> children_list; + for (auto& child : children) { log_assert(child->type == AST_ARGUMENT); log_assert(child->children.size() == 1); - children_list.push_back(child->children[0]); + children_list.push_back(std::move(child->children[0])); child->children.clear(); - delete child; } children.clear(); @@ -2782,39 +2754,38 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin std::vector z_const(1, RTLIL::State::Sz); - AstNode *mux_input = children_list.at(1); + auto& mux_input = children_list.at(1); if (str == "notif0" || str == "notif1") { - mux_input = new AstNode(AST_BIT_NOT, mux_input); + mux_input = std::make_unique(AST_BIT_NOT, std::move(mux_input)); } - AstNode *node = new AstNode(AST_TERNARY, children_list.at(2)); + auto node = std::make_unique(AST_TERNARY, std::move(children_list.at(2))); if (str == "bufif0") { node->children.push_back(AstNode::mkconst_bits(z_const, false)); - node->children.push_back(mux_input); + node->children.push_back(std::move(mux_input)); } else { - node->children.push_back(mux_input); + node->children.push_back(std::move(mux_input)); node->children.push_back(AstNode::mkconst_bits(z_const, false)); } str.clear(); type = AST_ASSIGN; - children.push_back(children_list.at(0)); + children.push_back(std::move(children_list.at(0))); children.back()->was_checked = true; - children.push_back(node); + children.push_back(std::move(node)); fixup_hierarchy_flags(); did_something = true; } else if (str == "buf" || str == "not") { - AstNode *input = children_list.back(); + auto& input = children_list.back(); if (str == "not") - input = new AstNode(AST_BIT_NOT, input); + input = std::make_unique(AST_BIT_NOT, std::move(input)); - newNode = new AstNode(AST_GENBLOCK); + newNode = std::make_unique(AST_GENBLOCK); for (auto it = children_list.begin(); it != std::prev(children_list.end()); it++) { - newNode->children.push_back(new AstNode(AST_ASSIGN, *it, input->clone())); + newNode->children.push_back(std::make_unique(AST_ASSIGN, std::move(*it), input->clone())); newNode->children.back()->was_checked = true; } - delete input; did_something = true; } @@ -2837,20 +2808,20 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin op_type = AST_BIT_XOR, invert_results = true; log_assert(op_type != AST_NONE); - AstNode *node = children_list[1]; + auto& node = children_list[1]; if (op_type != AST_POS) for (size_t i = 2; i < children_list.size(); i++) { - node = new AstNode(op_type, node, children_list[i]); + node = std::make_unique(op_type, std::move(node), std::move(children_list[i])); node->location = location; } if (invert_results) - node = new AstNode(AST_BIT_NOT, node); + node = std::make_unique(AST_BIT_NOT, std::move(node)); str.clear(); type = AST_ASSIGN; - children.push_back(children_list[0]); + children.push_back(std::move(children_list[0])); children.back()->was_checked = true; - children.push_back(node); + children.push_back(std::move(node)); fixup_hierarchy_flags(); did_something = true; } @@ -2865,7 +2836,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin goto skip_dynamic_range_lvalue_expansion; if (children[0]->children[0]->range_valid || did_something) goto skip_dynamic_range_lvalue_expansion; - if (children[0]->id2ast == NULL || children[0]->id2ast->type != AST_WIRE) + if (children[0]->id2ast == nullptr || children[0]->id2ast->type != AST_WIRE) goto skip_dynamic_range_lvalue_expansion; if (!children[0]->id2ast->range_valid) goto skip_dynamic_range_lvalue_expansion; @@ -2877,10 +2848,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin int wire_offset = children[0]->id2ast->range_right; int result_width = 1; - AstNode *shift_expr = NULL; - AstNode *range = children[0]->children[0]; + std::unique_ptr shift_expr = nullptr; + auto& range = children[0]->children[0]; - if (!try_determine_range_width(range, result_width)) + if (!try_determine_range_width(range.get(), result_width)) input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); if (range->children.size() >= 2) @@ -2924,14 +2895,14 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin AstNode *lsb_expr = shift_expr->type == AST_ADD && shift_expr->children[0]->type == AST_SELFSZ && shift_expr->children[1]->type == AST_CONSTANT && shift_expr->children[1]->integer == 0 ? - shift_expr->children[0]->children[0] : - shift_expr; + shift_expr->children[0]->children[0].get() : + shift_expr.get(); // Extract stride from indexing of two-dimensional packed arrays and // variable slices on the form dst[i*stride +: width] = src. if (lsb_expr->type == AST_MUL && - (lsb_expr->children[0]->type == AST_CONSTANT || - lsb_expr->children[1]->type == AST_CONSTANT)) + (lsb_expr->children[0]->type == AST_CONSTANT || + lsb_expr->children[1]->type == AST_CONSTANT)) { int stride_ix = lsb_expr->children[1]->type == AST_CONSTANT; stride = (int)lsb_expr->children[stride_ix]->integer; @@ -2979,11 +2950,14 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin int rvalue_width; bool rvalue_sign; children[1]->detectSignWidth(rvalue_width, rvalue_sign); - AstNode *rvalue = mktemp_logic("$bitselwrite$rvalue$", current_ast_mod, true, rvalue_width - 1, 0, rvalue_sign); - AstNode *caseNode = new AstNode(AST_CASE, shift_expr); - newNode = new AstNode(AST_BLOCK, - new AstNode(AST_ASSIGN_EQ, rvalue, children[1]->clone()), - caseNode); + auto rvalue = mktemp_logic("$bitselwrite$rvalue$", current_ast_mod, true, rvalue_width - 1, 0, rvalue_sign); + auto* rvalue_leaky = rvalue.get(); + log("make 1\n"); + auto case_node_owned = std::make_unique(AST_CASE, std::move(shift_expr)); + auto* case_node = case_node_owned.get(); + newNode = std::make_unique(AST_BLOCK, + std::make_unique(AST_ASSIGN_EQ, std::move(rvalue), children[1]->clone()), + std::move(case_node_owned)); did_something = true; for (int i = 1 - result_width; i < wire_width; i++) { @@ -2996,26 +2970,26 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (start_bit%bitno_div != 0 || (stride == 0 && start_bit != 0)) continue; - AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, case_sign_hint, max_width)); - AstNode *lvalue = children[0]->clone(); + auto cond = std::make_unique(AST_COND, mkconst_int(start_bit, case_sign_hint, max_width)); + auto lvalue = children[0]->clone(); lvalue->delete_children(); if (member_node) lvalue->set_attribute(ID::wiretype, member_node->clone()); - lvalue->children.push_back(new AstNode(AST_RANGE, + lvalue->children.push_back(std::make_unique(AST_RANGE, mkconst_int(end_bit, true), mkconst_int(start_bit, true))); - cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, rvalue->clone()))); - caseNode->children.push_back(cond); + cond->children.push_back(std::make_unique(AST_BLOCK, std::make_unique(std::move(type), std::move(lvalue), rvalue_leaky->clone()))); + case_node->children.push_back(std::move(cond)); } } else { // mask and shift operations // dst = (dst & ~(width'1 << lsb)) | unsigned'(width'(src)) << lsb) - AstNode *lvalue = children[0]->clone(); + auto lvalue = children[0]->clone(); lvalue->delete_children(); if (member_node) lvalue->set_attribute(ID::wiretype, member_node->clone()); - AstNode *old_data = lvalue->clone(); + auto old_data = lvalue->clone(); if (type == AST_ASSIGN_LE) old_data->lookahead = true; @@ -3024,51 +2998,52 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin shift_expr->detectSignWidth(shift_width_hint, shift_sign_hint); // All operations are carried out in a new block. - newNode = new AstNode(AST_BLOCK); + newNode = std::make_unique(AST_BLOCK); // Temporary register holding the result of the bit- or part-select position expression. - AstNode *pos = mktemp_logic("$bitselwrite$pos$", current_ast_mod, true, shift_width_hint - 1, 0, shift_sign_hint); - newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, pos, shift_expr)); - + auto pos = mktemp_logic("$bitselwrite$pos$", current_ast_mod, true, shift_width_hint - 1, 0, shift_sign_hint); // Calculate lsb from position. - AstNode *shift_val = pos->clone(); + auto shift_val = pos->clone(); + + newNode->children.push_back(std::make_unique(AST_ASSIGN_EQ, std::move(pos), std::move(shift_expr))); // If the expression is signed, we must add an extra bit for possible negation of the most negative number. // If the expression is unsigned, we must add an extra bit for sign. - shift_val = new AstNode(AST_CAST_SIZE, mkconst_int(shift_width_hint + 1, true), shift_val); + shift_val = std::make_unique(AST_CAST_SIZE, mkconst_int(shift_width_hint + 1, true), std::move(shift_val)); if (!shift_sign_hint) - shift_val = new AstNode(AST_TO_SIGNED, shift_val); + shift_val = std::make_unique(AST_TO_SIGNED, std::move(shift_val)); // offset the shift amount by the lower bound of the dimension if (wire_offset != 0) - shift_val = new AstNode(AST_SUB, shift_val, mkconst_int(wire_offset, true)); + shift_val = std::make_unique(AST_SUB, std::move(shift_val), mkconst_int(wire_offset, true)); // reflect the shift amount if the dimension is swapped if (children[0]->id2ast->range_swapped) - shift_val = new AstNode(AST_SUB, mkconst_int(wire_width - result_width, true), shift_val); + shift_val = std::make_unique(AST_SUB, mkconst_int(wire_width - result_width, true), std::move(shift_val)); // AST_SHIFT uses negative amounts for shifting left - shift_val = new AstNode(AST_NEG, shift_val); + shift_val = std::make_unique(AST_NEG, std::move(shift_val)); + auto also_shift_val = shift_val->clone(); // dst = (dst & ~(width'1 << lsb)) | unsigned'(width'(src)) << lsb) did_something = true; - AstNode *bitmask = mkconst_bits(std::vector(result_width, State::S1), false); + auto bitmask = mkconst_bits(std::vector(result_width, State::S1), false); newNode->children.push_back( - new AstNode(type, - lvalue, - new AstNode(AST_BIT_OR, - new AstNode(AST_BIT_AND, - old_data, - new AstNode(AST_BIT_NOT, - new AstNode(AST_SHIFT, - bitmask, - shift_val->clone()))), - new AstNode(AST_SHIFT, - new AstNode(AST_TO_UNSIGNED, - new AstNode(AST_CAST_SIZE, - mkconst_int(result_width, true), - children[1]->clone())), - shift_val)))); + std::make_unique(std::move(type), + std::move(lvalue), + std::make_unique(AST_BIT_OR, + std::make_unique(AST_BIT_AND, + std::move(old_data), + std::make_unique(AST_BIT_NOT, + std::make_unique(AST_SHIFT, + std::move(bitmask), + std::move(shift_val)))), + std::make_unique(AST_SHIFT, + std::make_unique(AST_TO_UNSIGNED, + std::make_unique(AST_CAST_SIZE, + mkconst_int(result_width, true), + children[1]->clone())), + std::move(also_shift_val))))); newNode->fixup_hierarchy_flags(true); } @@ -3078,11 +3053,11 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin skip_dynamic_range_lvalue_expansion:; // found right-hand side identifier for memory -> replace with memory read port - if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue && + if (stage > 1 && type == AST_IDENTIFIER && id2ast != nullptr && id2ast->type == AST_MEMORY && !in_lvalue && children.size() == 1 && children[0]->type == AST_RANGE && children[0]->children.size() == 1) { if (integer < (unsigned)id2ast->unpacked_dimensions) input_error("Insufficient number of array indices for %s.\n", log_id(str)); - newNode = new AstNode(AST_MEMRD, children[0]->children[0]->clone()); + newNode = std::make_unique(AST_MEMRD, children[0]->children[0]->clone()); newNode->str = str; newNode->id2ast = id2ast; goto apply_newNode; @@ -3093,39 +3068,41 @@ skip_dynamic_range_lvalue_expansion:; { bool found_nontrivial_member = false; - for (auto child : children[0]->children) { - if (child->type == AST_IDENTIFIER && child->id2ast != NULL && child->id2ast->type == AST_MEMORY) + for (auto& child : children[0]->children) { + if (child->type == AST_IDENTIFIER && child->id2ast != nullptr && child->id2ast->type == AST_MEMORY) found_nontrivial_member = true; } if (found_nontrivial_member) { - newNode = new AstNode(AST_BLOCK); + newNode = std::make_unique(AST_BLOCK); - AstNode *wire_tmp = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true))); + auto wire_tmp_owned = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true))); + auto wire_tmp = wire_tmp_owned.get(); wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++); - current_ast_mod->children.push_back(wire_tmp); current_scope[wire_tmp->str] = wire_tmp; + current_ast_mod->children.push_back(std::move(wire_tmp_owned)); wire_tmp->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); while (wire_tmp->simplify(true, 1, -1, false)) { } wire_tmp->is_logic = true; - AstNode *wire_tmp_id = new AstNode(AST_IDENTIFIER); + auto wire_tmp_id_owned = std::make_unique(AST_IDENTIFIER); + auto* wire_tmp_id = wire_tmp_id_owned.get(); wire_tmp_id->str = wire_tmp->str; - newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, wire_tmp_id, children[1]->clone())); + newNode->children.push_back(std::make_unique(AST_ASSIGN_EQ, std::move(wire_tmp_id_owned), children[1]->clone())); newNode->children.back()->was_checked = true; int cursor = 0; - for (auto child : children[0]->children) + for (auto& child : children[0]->children) { int child_width_hint = -1; bool child_sign_hint = true; child->detectSignWidth(child_width_hint, child_sign_hint); - AstNode *rhs = wire_tmp_id->clone(); - rhs->children.push_back(new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+child_width_hint-1, true), AstNode::mkconst_int(cursor, true))); - newNode->children.push_back(new AstNode(type, child->clone(), rhs)); + auto rhs = wire_tmp_id->clone(); + rhs->children.push_back(std::make_unique(AST_RANGE, AstNode::mkconst_int(cursor+child_width_hint-1, true), AstNode::mkconst_int(cursor, true))); + newNode->children.push_back(std::make_unique(type, child->clone(), std::move(rhs))); cursor += child_width_hint; } @@ -3151,8 +3128,8 @@ skip_dynamic_range_lvalue_expansion:; bool mem_signed = children[0]->id2ast->is_signed; children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); - newNode = new AstNode(AST_BLOCK); - AstNode *defNode = new AstNode(AST_BLOCK); + newNode = std::make_unique(AST_BLOCK); + auto defNode = std::make_unique(AST_BLOCK); int data_range_left = children[0]->id2ast->children[0]->range_left; int data_range_right = children[0]->id2ast->children[0]->range_right; @@ -3171,74 +3148,75 @@ skip_dynamic_range_lvalue_expansion:; for (int i = 0; i < mem_width; i++) set_bits_en.push_back(RTLIL::State::S1); - AstNode *node_addr = nullptr; + std::unique_ptr node_addr = nullptr; if (children[0]->children[0]->children[0]->isConst()) { node_addr = children[0]->children[0]->children[0]->clone(); } else { - AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); + auto wire_addr_owned = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); + auto* wire_addr = wire_addr_owned.get(); wire_addr->str = id_addr; wire_addr->was_checked = true; - current_ast_mod->children.push_back(wire_addr); + current_ast_mod->children.push_back(std::move(wire_addr_owned)); current_scope[wire_addr->str] = wire_addr; while (wire_addr->simplify(true, 1, -1, false)) { } - AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false)); + auto assign_addr = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false)); assign_addr->children[0]->str = id_addr; assign_addr->children[0]->was_checked = true; - defNode->children.push_back(assign_addr); + defNode->children.push_back(std::move(assign_addr)); - assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); + assign_addr = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); assign_addr->children[0]->str = id_addr; assign_addr->children[0]->was_checked = true; - newNode->children.push_back(assign_addr); + newNode->children.push_back(std::move(assign_addr)); - node_addr = new AstNode(AST_IDENTIFIER); + node_addr = std::make_unique(AST_IDENTIFIER); node_addr->str = id_addr; } - AstNode *node_data = nullptr; + std::unique_ptr node_data = nullptr; if (children[0]->children.size() == 1 && children[1]->isConst()) { node_data = children[1]->clone(); } else { - AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); + auto wire_data_owned = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); + auto* wire_data = wire_data_owned.get(); wire_data->str = id_data; wire_data->was_checked = true; wire_data->is_signed = mem_signed; - current_ast_mod->children.push_back(wire_data); current_scope[wire_data->str] = wire_data; + current_ast_mod->children.push_back(std::move(wire_data_owned)); while (wire_data->simplify(true, 1, -1, false)) { } - AstNode *assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false)); + auto assign_data = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), mkconst_bits(x_bits_data, false)); assign_data->children[0]->str = id_data; assign_data->children[0]->was_checked = true; - defNode->children.push_back(assign_data); + defNode->children.push_back(std::move(assign_data)); - node_data = new AstNode(AST_IDENTIFIER); + node_data = std::make_unique(AST_IDENTIFIER); node_data->str = id_data; } - AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); + auto wire_en_owned = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); + auto* wire_en = wire_en_owned.get(); wire_en->str = id_en; wire_en->was_checked = true; - current_ast_mod->children.push_back(wire_en); current_scope[wire_en->str] = wire_en; + current_ast_mod->children.push_back(std::move(wire_en_owned)); while (wire_en->simplify(true, 1, -1, false)) { } - AstNode *assign_en_first = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width)); + auto assign_en_first = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), mkconst_int(0, false, mem_width)); assign_en_first->children[0]->str = id_en; assign_en_first->children[0]->was_checked = true; - defNode->children.push_back(assign_en_first); + defNode->children.push_back(std::move(assign_en_first)); - AstNode *node_en = new AstNode(AST_IDENTIFIER); + auto node_en = std::make_unique(AST_IDENTIFIER); node_en->str = id_en; if (!defNode->children.empty()) - current_top_block->children.insert(current_top_block->children.begin(), defNode); - else - delete defNode; + current_top_block->children.insert(current_top_block->children.begin(), std::move(defNode)); - AstNode *assign_data = nullptr; - AstNode *assign_en = nullptr; + std::unique_ptr assign_data = nullptr; + std::unique_ptr assign_en = nullptr; if (children[0]->children.size() == 2) { if (children[0]->children[1]->range_valid) @@ -3249,24 +3227,24 @@ skip_dynamic_range_lvalue_expansion:; std::vector padding_x(offset, RTLIL::State::Sx); - assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), - new AstNode(AST_CONCAT, mkconst_bits(padding_x, false), children[1]->clone())); + assign_data = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), + std::make_unique(AST_CONCAT, mkconst_bits(padding_x, false), children[1]->clone())); assign_data->children[0]->str = id_data; assign_data->children[0]->was_checked = true; for (int i = 0; i < mem_width; i++) set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0; - assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false)); + assign_en = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), mkconst_bits(set_bits_en, false)); assign_en->children[0]->str = id_en; assign_en->children[0]->was_checked = true; } else { - AstNode *the_range = children[0]->children[1]; - AstNode *offset_ast; + std::unique_ptr& the_range = children[0]->children[1]; + std::unique_ptr offset_ast; int width; - if (!try_determine_range_width(the_range, width)) + if (!try_determine_range_width(the_range.get(), width)) input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); if (the_range->children.size() >= 2) @@ -3275,44 +3253,43 @@ skip_dynamic_range_lvalue_expansion:; offset_ast = the_range->children[0]->clone(); if (mem_data_range_offset) - offset_ast = new AstNode(AST_SUB, offset_ast, mkconst_int(mem_data_range_offset, true)); + offset_ast = std::make_unique(AST_SUB, std::move(offset_ast), mkconst_int(mem_data_range_offset, true)); - assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), - new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone())); + assign_data = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), + std::make_unique(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone())); assign_data->children[0]->str = id_data; assign_data->children[0]->was_checked = true; for (int i = 0; i < mem_width; i++) set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0; - assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), - new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone())); + assign_en = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), + std::make_unique(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone())); assign_en->children[0]->str = id_en; assign_en->children[0]->was_checked = true; - delete offset_ast; } } else { if (!(children[0]->children.size() == 1 && children[1]->isConst())) { - assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[1]->clone()); + assign_data = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), children[1]->clone()); assign_data->children[0]->str = id_data; assign_data->children[0]->was_checked = true; } - assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false)); + assign_en = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), mkconst_bits(set_bits_en, false)); assign_en->children[0]->str = id_en; assign_en->children[0]->was_checked = true; } if (assign_data) - newNode->children.push_back(assign_data); + newNode->children.push_back(std::move(assign_data)); if (assign_en) - newNode->children.push_back(assign_en); + newNode->children.push_back(std::move(assign_en)); - AstNode *wrnode; + std::unique_ptr wrnode; if (current_always->type == AST_INITIAL) - wrnode = new AstNode(AST_MEMINIT, node_addr, node_data, node_en, mkconst_int(1, false)); + wrnode = std::make_unique(AST_MEMINIT, std::move(node_addr), std::move(node_data), std::move(node_en), mkconst_int(1, false)); else - wrnode = new AstNode(AST_MEMWR, node_addr, node_data, node_en); + wrnode = std::make_unique(AST_MEMWR, std::move(node_addr), std::move(node_data), std::move(node_en)); wrnode->str = children[0]->str; wrnode->id2ast = children[0]->id2ast; wrnode->location = location; @@ -3326,14 +3303,13 @@ skip_dynamic_range_lvalue_expansion:; } wrnode->children.push_back(mkconst_bits(priority_mask, false)); current_memwr_visible[wrnode->str].insert(portid); - current_always->children.push_back(wrnode); + current_always->children.push_back(std::move(wrnode)); } else { - current_ast_mod->children.push_back(wrnode); + current_ast_mod->children.push_back(std::move(wrnode)); } if (newNode->children.empty()) { - delete newNode; - newNode = new AstNode(); + newNode = std::make_unique(); } goto apply_newNode; } @@ -3347,21 +3323,22 @@ skip_dynamic_range_lvalue_expansion:; { int myidx = autoidx++; - AstNode *wire = new AstNode(AST_WIRE); + auto wire_owned = std::make_unique(AST_WIRE); + auto* wire = wire_owned.get(); + current_ast_mod->children.push_back(std::move(wire_owned)); wire->str = stringf("$initstate$%d_wire", myidx); - current_ast_mod->children.push_back(wire); while (wire->simplify(true, 1, -1, false)) { } - AstNode *cell = new AstNode(AST_CELL, new AstNode(AST_CELLTYPE), new AstNode(AST_ARGUMENT, new AstNode(AST_IDENTIFIER))); + auto cell = std::make_unique(AST_CELL, std::make_unique(AST_CELLTYPE), std::make_unique(AST_ARGUMENT, std::make_unique(AST_IDENTIFIER))); cell->str = stringf("$initstate$%d", myidx); cell->children[0]->str = "$initstate"; cell->children[1]->str = "\\Y"; cell->children[1]->children[0]->str = wire->str; cell->children[1]->children[0]->id2ast = wire; - current_ast_mod->children.push_back(cell); + current_ast_mod->children.push_back(std::move(cell)); while (cell->simplify(true, 1, -1, false)) { } - newNode = new AstNode(AST_IDENTIFIER); + newNode = std::make_unique(AST_IDENTIFIER); newNode->str = wire->str; newNode->id2ast = wire; goto apply_newNode; @@ -3384,20 +3361,19 @@ skip_dynamic_range_lvalue_expansion:; if (GetSize(children) == 2) { - AstNode *buf = children[1]->clone(); + auto buf = children[1]->clone(); while (buf->simplify(true, stage, -1, false)) { } if (buf->type != AST_CONSTANT) input_error("Failed to evaluate system function `%s' with non-constant value.\n", str.c_str()); num_steps = buf->asInt(true); - delete buf; } AstNode *block = nullptr; - for (auto child : current_always->children) + for (auto& child : current_always->children) if (child->type == AST_BLOCK) - block = child; + block = child.get(); log_assert(block != nullptr); @@ -3407,41 +3383,42 @@ skip_dynamic_range_lvalue_expansion:; } int myidx = autoidx++; - AstNode *outreg = nullptr; + AstNode* outreg = nullptr; for (int i = 0; i < num_steps; i++) { - AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE, + auto reg_owned = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true))); + auto* reg = reg_owned.get(); + current_ast_mod->children.push_back(std::move(reg_owned)); reg->str = stringf("$past$%s:%d$%d$%d", RTLIL::encode_filename(filename).c_str(), location.first_line, myidx, i); reg->is_reg = true; reg->is_signed = sign_hint; - current_ast_mod->children.push_back(reg); while (reg->simplify(true, 1, -1, false)) { } - AstNode *regid = new AstNode(AST_IDENTIFIER); + auto regid = std::make_unique(AST_IDENTIFIER); regid->str = reg->str; regid->id2ast = reg; regid->was_checked = true; - AstNode *rhs = nullptr; + std::unique_ptr rhs = nullptr; if (outreg == nullptr) { rhs = children.at(0)->clone(); } else { - rhs = new AstNode(AST_IDENTIFIER); + rhs = std::make_unique(AST_IDENTIFIER); rhs->str = outreg->str; rhs->id2ast = outreg; } - block->children.push_back(new AstNode(AST_ASSIGN_LE, regid, rhs)); + block->children.push_back(std::make_unique(AST_ASSIGN_LE, std::move(regid), std::move(rhs))); outreg = reg; } - newNode = new AstNode(AST_IDENTIFIER); + newNode = std::make_unique(AST_IDENTIFIER); newNode->str = outreg->str; newNode->id2ast = outreg; goto apply_newNode; @@ -3457,25 +3434,25 @@ skip_dynamic_range_lvalue_expansion:; input_error("System function %s is only allowed in clocked blocks.\n", RTLIL::unescape_id(str).c_str()); - AstNode *present = children.at(0)->clone(); - AstNode *past = clone(); + auto present = children.at(0)->clone(); + auto past = clone(); past->str = "\\$past"; if (str == "\\$stable") - newNode = new AstNode(AST_EQ, past, present); + newNode = std::make_unique(AST_EQ, std::move(past), std::move(present)); else if (str == "\\$changed") - newNode = new AstNode(AST_NE, past, present); + newNode = std::make_unique(AST_NE, std::move(past), std::move(present)); else if (str == "\\$rose") - newNode = new AstNode(AST_LOGIC_AND, - new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, past, mkconst_int(1,false))), - new AstNode(AST_BIT_AND, present, mkconst_int(1,false))); + newNode = std::make_unique(AST_LOGIC_AND, + std::make_unique(AST_LOGIC_NOT, std::make_unique(AST_BIT_AND, std::move(past), mkconst_int(1,false))), + std::make_unique(AST_BIT_AND, std::move(present), mkconst_int(1,false))); else if (str == "\\$fell") - newNode = new AstNode(AST_LOGIC_AND, - new AstNode(AST_BIT_AND, past, mkconst_int(1,false)), - new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, present, mkconst_int(1,false)))); + newNode = std::make_unique(AST_LOGIC_AND, + std::make_unique(AST_BIT_AND, std::move(past), mkconst_int(1,false)), + std::make_unique(AST_LOGIC_NOT, std::make_unique(AST_BIT_AND, std::move(present), mkconst_int(1,false)))); else log_abort(); @@ -3495,7 +3472,7 @@ skip_dynamic_range_lvalue_expansion:; input_error("System function %s got %d arguments, expected 1.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); - AstNode *buf = children[0]->clone(); + auto buf = children[0]->clone(); while (buf->simplify(true, stage, width_hint, sign_hint)) { } if (buf->type != AST_CONSTANT) input_error("Failed to evaluate system function `%s' with non-constant value.\n", str.c_str()); @@ -3503,7 +3480,6 @@ skip_dynamic_range_lvalue_expansion:; RTLIL::Const arg_value = buf->bitsAsConst(); if (arg_value.as_bool()) arg_value = const_sub(arg_value, 1, false, false, GetSize(arg_value)); - delete buf; uint32_t result = 0; for (auto i = 0; i < arg_value.size(); i++) @@ -3515,7 +3491,7 @@ skip_dynamic_range_lvalue_expansion:; } if (str == "\\$dimensions" || str == "\\$unpacked_dimensions" || - str == "\\$increment" || str == "\\$size" || str == "\\$bits" || str == "\\$high" || str == "\\$low" || str == "\\$left" || str == "\\$right") + str == "\\$increment" || str == "\\$size" || str == "\\$bits" || str == "\\$high" || str == "\\$low" || str == "\\$left" || str == "\\$right") { int dim = 1; if (str == "\\$dimensions" || str == "\\$unpacked_dimensions" || str == "\\$bits") { @@ -3527,24 +3503,23 @@ skip_dynamic_range_lvalue_expansion:; input_error("System function %s got %d arguments, expected 1 or 2.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); if (children.size() == 2) { - AstNode *buf = children[1]->clone(); + auto buf = children[1]->clone(); // Evaluate constant expression while (buf->simplify(true, stage, width_hint, sign_hint)) { } dim = buf->asInt(false); - delete buf; } } - AstNode *buf = children[0]->clone(); + auto buf = children[0]->clone(); int mem_depth = 1; int result, high = 0, low = 0, left = 0, right = 0, width = 1; // defaults for a simple wire int expr_dimensions = 0, expr_unpacked_dimensions = 0; - AstNode *id_ast = NULL; + AstNode *id_ast = nullptr; buf->detectSignWidth(width_hint, sign_hint); if (buf->type == AST_IDENTIFIER) { id_ast = buf->id2ast; - if (id_ast == NULL && current_scope.count(buf->str)) + if (id_ast == nullptr && current_scope.count(buf->str)) id_ast = current_scope.at(buf->str); if (!id_ast) input_error("Failed to resolve identifier %s for width detection!\n", buf->str.c_str()); @@ -3583,7 +3558,6 @@ skip_dynamic_range_lvalue_expansion:; left = high = width - 1; expr_dimensions = 1; } - delete buf; if (str == "\\$dimensions") result = expr_dimensions; else if (str == "\\$unpacked_dimensions") @@ -3651,8 +3625,8 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$rtoi") { newNode = AstNode::mkconst_int(x, true); } else { - newNode = new AstNode(AST_REALVALUE); - if (str == "\\$ln") newNode->realvalue = ::log(x); + newNode = std::make_unique(AST_REALVALUE); + if (str == "\\$ln") newNode->realvalue = ::log(x); else if (str == "\\$log10") newNode->realvalue = ::log10(x); else if (str == "\\$exp") newNode->realvalue = ::exp(x); else if (str == "\\$sqrt") newNode->realvalue = ::sqrt(x); @@ -3694,7 +3668,7 @@ skip_dynamic_range_lvalue_expansion:; // Determine which bits to count for (size_t i = 1; i < children.size(); i++) { - AstNode *node = children[i]; + auto& node = children[i]; while (node->simplify(true, stage, -1, false)) { } if (node->type != AST_CONSTANT) input_error("Failed to evaluate system function `%s' with non-constant control bit argument.\n", str.c_str()); @@ -3706,39 +3680,37 @@ skip_dynamic_range_lvalue_expansion:; // Detect width of exp (first argument of $countbits) int exp_width = -1; bool exp_sign = false; - AstNode *exp = children[0]; - exp->detectSignWidth(exp_width, exp_sign, NULL); + auto& exp = children[0]; + exp->detectSignWidth(exp_width, exp_sign, nullptr); newNode = mkconst_int(0, false); for (int i = 0; i < exp_width; i++) { // Generate nodes for: exp << i >> ($size(exp) - 1) - // ^^ ^^ - AstNode *lsh_node = new AstNode(AST_SHIFT_LEFT, exp->clone(), mkconst_int(i, false)); - AstNode *rsh_node = new AstNode(AST_SHIFT_RIGHT, lsh_node, mkconst_int(exp_width - 1, false)); + // ^^ ^^ + auto lsh_node = std::make_unique(AST_SHIFT_LEFT, exp->clone(), mkconst_int(i, false)); + auto rsh_node = std::make_unique(AST_SHIFT_RIGHT, std::move(lsh_node), mkconst_int(exp_width - 1, false)); - AstNode *or_node = nullptr; + std::unique_ptr or_node = nullptr; for (RTLIL::State control_bit : control_bits) { // Generate node for: (exp << i >> ($size(exp) - 1)) === control_bit - // ^^^ - AstNode *eq_node = new AstNode(AST_EQX, rsh_node->clone(), mkconst_bits({control_bit}, false)); + // ^^^ + auto eq_node = std::make_unique(AST_EQX, rsh_node->clone(), mkconst_bits({control_bit}, false)); // Or the result for each checked bit value if (or_node) - or_node = new AstNode(AST_LOGIC_OR, or_node, eq_node); + or_node = std::make_unique(AST_LOGIC_OR, std::move(or_node), std::move(eq_node)); else - or_node = eq_node; + or_node = std::move(eq_node); } // We should have at least one element in control_bits, // because we checked for the number of arguments above log_assert(or_node != nullptr); - delete rsh_node; - // Generate node for adding with result of previous bit - newNode = new AstNode(AST_ADD, newNode, or_node); + newNode = std::make_unique(AST_ADD, std::move(newNode), std::move(or_node)); } goto apply_newNode; @@ -3749,22 +3721,22 @@ skip_dynamic_range_lvalue_expansion:; input_error("System function %s got %d arguments, expected 1.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); - AstNode *countbits = clone(); + auto countbits = clone(); countbits->str = "\\$countbits"; if (str == "\\$countones") { countbits->children.push_back(mkconst_bits({RTLIL::State::S1}, false)); - newNode = countbits; + newNode = std::move(countbits); } else if (str == "\\$isunknown") { countbits->children.push_back(mkconst_bits({RTLIL::Sx}, false)); countbits->children.push_back(mkconst_bits({RTLIL::Sz}, false)); - newNode = new AstNode(AST_GT, countbits, mkconst_int(0, false)); + newNode = std::make_unique(AST_GT, std::move(countbits), mkconst_int(0, false)); } else if (str == "\\$onehot") { countbits->children.push_back(mkconst_bits({RTLIL::State::S1}, false)); - newNode = new AstNode(AST_EQ, countbits, mkconst_int(1, false)); + newNode = std::make_unique(AST_EQ, std::move(countbits), mkconst_int(1, false)); } else if (str == "\\$onehot0") { countbits->children.push_back(mkconst_bits({RTLIL::State::S1}, false)); - newNode = new AstNode(AST_LE, countbits, mkconst_int(1, false)); + newNode = std::make_unique(AST_LE, std::move(countbits), mkconst_int(1, false)); } else { log_abort(); } @@ -3778,7 +3750,7 @@ skip_dynamic_range_lvalue_expansion:; std::string rtype, fname; std::vector argtypes; - std::vector args; + std::vector> args; rtype = RTLIL::unescape_id(dpi_decl->children.at(0)->str); fname = RTLIL::unescape_id(dpi_decl->children.at(1)->str); @@ -3798,9 +3770,6 @@ skip_dynamic_range_lvalue_expansion:; newNode = dpi_call(rtype, fname, argtypes, args); - for (auto arg : args) - delete arg; - goto apply_newNode; } @@ -3826,12 +3795,12 @@ skip_dynamic_range_lvalue_expansion:; input_error("System function %s got %d arguments, expected 2-4.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); - AstNode *node_filename = children[0]->clone(); + auto node_filename = children[0]->clone(); while (node_filename->simplify(true, stage, width_hint, sign_hint)) { } if (node_filename->type != AST_CONSTANT) input_error("Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str()); - AstNode *node_memory = children[1]->clone(); + auto node_memory = children[1]->clone(); while (node_memory->simplify(true, stage, width_hint, sign_hint)) { } if (node_memory->type != AST_IDENTIFIER || node_memory->id2ast == nullptr || node_memory->id2ast->type != AST_MEMORY) input_error("Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str.c_str()); @@ -3839,7 +3808,7 @@ skip_dynamic_range_lvalue_expansion:; int start_addr = -1, finish_addr = -1; if (GetSize(children) > 2) { - AstNode *node_addr = children[2]->clone(); + auto node_addr = children[2]->clone(); while (node_addr->simplify(true, stage, width_hint, sign_hint)) { } if (node_addr->type != AST_CONSTANT) input_error("Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str.c_str()); @@ -3847,7 +3816,7 @@ skip_dynamic_range_lvalue_expansion:; } if (GetSize(children) > 3) { - AstNode *node_addr = children[3]->clone(); + auto node_addr = children[3]->clone(); while (node_addr->simplify(true, stage, width_hint, sign_hint)) { } if (node_addr->type != AST_CONSTANT) input_error("Failed to evaluate system function `%s' with non-constant 4th argument.\n", str.c_str()); @@ -3858,22 +3827,20 @@ skip_dynamic_range_lvalue_expansion:; if (current_always->type == AST_INITIAL) { pool queue; log_assert(current_always->children[0]->type == AST_BLOCK); - queue.insert(current_always->children[0]); + queue.insert(current_always->children[0].get()); while (!unconditional_init && !queue.empty()) { pool next_queue; - for (auto n : queue) - for (auto c : n->children) { - if (c == this) + for (auto& n : queue) + for (auto& c : n->children) { + if (c.get() == this) unconditional_init = true; - next_queue.insert(c); + next_queue.insert(c.get()); } next_queue.swap(queue); } } newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init); - delete node_filename; - delete node_memory; goto apply_newNode; } @@ -3888,10 +3855,11 @@ skip_dynamic_range_lvalue_expansion:; sstr << str << "$func$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++) << '.'; std::string prefix = sstr.str(); - AstNode *decl = current_scope[str]; + auto* decl = current_scope[str]; if (unevaluated_tern_branch && decl->is_recursive_function()) goto replace_fcall_later; - decl = decl->clone(); + auto decl_clone = decl->clone(); + decl = decl_clone.get(); // sketchy? decl->replace_result_wire_name_in_function(str, "$result"); // enables recursion decl->expand_genblock(prefix); @@ -3899,20 +3867,19 @@ skip_dynamic_range_lvalue_expansion:; { bool require_const_eval = decl->has_const_only_constructs(); bool all_args_const = true; - for (auto child : children) { + for (auto& child : children) { while (child->simplify(true, 1, -1, false)) { } if (child->type != AST_CONSTANT && child->type != AST_REALVALUE) all_args_const = false; } if (all_args_const) { - AstNode *func_workspace = decl->clone(); + auto func_workspace = decl->clone(); func_workspace->set_in_param_flag(true); func_workspace->str = prefix_id(prefix, "$result"); + // func_workspace->dumpAst(stdout, "func_workspace "); newNode = func_workspace->eval_const_function(this, in_param || require_const_eval); - delete func_workspace; if (newNode) { - delete decl; goto apply_newNode; } } @@ -3925,36 +3892,37 @@ skip_dynamic_range_lvalue_expansion:; size_t arg_count = 0; dict wire_cache; - vector new_stmts; - vector output_assignments; + vector> new_stmts; + vector> output_assignments; - if (current_block == NULL) + if (current_block == nullptr) { log_assert(type == AST_FCALL); - AstNode *wire = NULL; + std::unique_ptr wire = nullptr; std::string res_name = prefix_id(prefix, "$result"); - for (auto child : decl->children) + for (auto& child : decl->children) if (child->type == AST_WIRE && child->str == res_name) wire = child->clone(); - log_assert(wire != NULL); + log_assert(wire != nullptr); wire->port_id = 0; wire->is_input = false; wire->is_output = false; - current_scope[wire->str] = wire; - current_ast_mod->children.push_back(wire); - while (wire->simplify(true, 1, -1, false)) { } + auto* wire_leaky = wire.get(); + current_scope[wire->str] = wire_leaky; + current_ast_mod->children.push_back(std::move(wire)); + while (wire_leaky->simplify(true, 1, -1, false)) { } - AstNode *lvalue = new AstNode(AST_IDENTIFIER); - lvalue->str = wire->str; + auto lvalue = std::make_unique(AST_IDENTIFIER); + lvalue->str = wire_leaky->str; - AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK, - new AstNode(AST_ASSIGN_EQ, lvalue, clone()))); + auto always = std::make_unique(AST_ALWAYS, std::make_unique(AST_BLOCK, + std::make_unique(AST_ASSIGN_EQ, std::move(lvalue), clone()))); always->children[0]->children[0]->was_checked = true; - current_ast_mod->children.push_back(always); + current_ast_mod->children.push_back(std::move(always)); goto replace_fcall_with_id; } @@ -3971,57 +3939,57 @@ skip_dynamic_range_lvalue_expansion:; } else celltype = RTLIL::escape_id(celltype); - AstNode *cell = new AstNode(AST_CELL, new AstNode(AST_CELLTYPE)); + auto cell = std::make_unique(AST_CELL, std::make_unique(AST_CELLTYPE)); cell->str = prefix.substr(0, GetSize(prefix)-1); cell->children[0]->str = celltype; - for (auto attr : decl->attributes) + for (auto& attr : decl->attributes) if (attr.first.str().rfind("\\via_celltype_defparam_", 0) == 0) { - AstNode *cell_arg = new AstNode(AST_PARASET, attr.second->clone()); + auto cell_arg = std::make_unique(AST_PARASET, attr.second->clone()); cell_arg->str = RTLIL::escape_id(attr.first.substr(strlen("\\via_celltype_defparam_"))); - cell->children.push_back(cell_arg); + cell->children.push_back(std::move(cell_arg)); } - for (auto child : decl->children) + for (auto& child : decl->children) if (child->type == AST_WIRE && (child->is_input || child->is_output || (type == AST_FCALL && child->str == str))) { - AstNode *wire = child->clone(); + auto wire = child->clone(); wire->port_id = 0; wire->is_input = false; wire->is_output = false; - current_ast_mod->children.push_back(wire); + current_ast_mod->children.push_back(std::move(wire)); while (wire->simplify(true, 1, -1, false)) { } - AstNode *wire_id = new AstNode(AST_IDENTIFIER); + auto wire_id = std::make_unique(AST_IDENTIFIER); wire_id->str = wire->str; if ((child->is_input || child->is_output) && arg_count < children.size()) { - AstNode *arg = children[arg_count++]->clone(); - AstNode *assign = child->is_input ? - new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) : - new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone()); + auto arg = children[arg_count++]->clone(); + auto assign = child->is_input ? + std::make_unique(AST_ASSIGN_EQ, wire_id->clone(), std::move(arg)) : + std::make_unique(AST_ASSIGN_EQ, std::move(arg), wire_id->clone()); assign->children[0]->was_checked = true; for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { - if (*it != current_block_child) + if (it->get() != current_block_child) continue; - current_block->children.insert(it, assign); + current_block->children.insert(it, std::move(assign)); break; } } - AstNode *cell_arg = new AstNode(AST_ARGUMENT, wire_id); + auto cell_arg = std::make_unique(AST_ARGUMENT, std::move(wire_id)); cell_arg->str = child->str == str ? outport : child->str; - cell->children.push_back(cell_arg); + cell->children.push_back(std::move(cell_arg)); } - current_ast_mod->children.push_back(cell); + current_ast_mod->children.push_back(std::move(cell)); goto replace_fcall_with_id; } - for (auto child : decl->children) + for (auto& child : decl->children) if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_ENUM_ITEM) { AstNode *wire = nullptr; @@ -4031,7 +3999,7 @@ skip_dynamic_range_lvalue_expansion:; wire = wire_cache.at(child->str); bool contains_value = wire->type == AST_LOCALPARAM; if (wire->children.size() == contains_value) { - for (auto c : child->children) + for (auto& c : child->children) wire->children.push_back(c->clone()); } else if (!child->children.empty()) { while (child->simplify(true, stage, -1, false)) { } @@ -4047,38 +4015,36 @@ skip_dynamic_range_lvalue_expansion:; } else { - wire = child->clone(); + current_ast_mod->children.push_back(child->clone()); + wire = current_ast_mod->children.back().get(); wire->port_id = 0; wire->is_input = false; wire->is_output = false; wire->is_reg = true; wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); if (child->type == AST_ENUM_ITEM) - wire->set_attribute(ID::enum_base_type, child->attributes[ID::enum_base_type]); + wire->set_attribute(ID::enum_base_type, std::move(child->attributes[ID::enum_base_type])); wire_cache[child->str] = wire; current_scope[wire->str] = wire; - current_ast_mod->children.push_back(wire); } while (wire->simplify(true, 1, -1, false)) { } if ((child->is_input || child->is_output) && arg_count < children.size()) { - AstNode *arg = children[arg_count++]->clone(); + auto arg = children[arg_count++]->clone(); // convert purely constant arguments into localparams - if (child->is_input && child->type == AST_WIRE && arg->type == AST_CONSTANT && node_contains_assignment_to(decl, child)) { + if (child->is_input && child->type == AST_WIRE && arg->type == AST_CONSTANT && node_contains_assignment_to(decl, child.get())) { wire->type = AST_LOCALPARAM; - if (wire->attributes.count(ID::nosync)) - delete wire->attributes.at(ID::nosync); wire->attributes.erase(ID::nosync); wire->children.insert(wire->children.begin(), arg->clone()); // args without a range implicitly have width 1 if (wire->children.back()->type != AST_RANGE) { // check if this wire is redeclared with an explicit size bool uses_explicit_size = false; - for (const AstNode *other_child : decl->children) + for (auto& other_child : decl->children) if (other_child->type == AST_WIRE && child->str == other_child->str && !other_child->children.empty() && other_child->children.back()->type == AST_RANGE) { @@ -4086,48 +4052,49 @@ skip_dynamic_range_lvalue_expansion:; break; } if (!uses_explicit_size) { - AstNode* range = new AstNode(); + auto range = std::make_unique(); range->type = AST_RANGE; - wire->children.push_back(range); range->children.push_back(mkconst_int(0, true)); range->children.push_back(mkconst_int(0, true)); + wire->children.push_back(std::move(range)); } } wire->fixup_hierarchy_flags(); // updates the sizing while (wire->simplify(true, 1, -1, false)) { } - delete arg; continue; } - AstNode *wire_id = new AstNode(AST_IDENTIFIER); + auto wire_id = std::make_unique(AST_IDENTIFIER); wire_id->str = wire->str; - AstNode *assign = child->is_input ? - new AstNode(AST_ASSIGN_EQ, wire_id, arg) : - new AstNode(AST_ASSIGN_EQ, arg, wire_id); + auto assign = child->is_input ? + std::make_unique(AST_ASSIGN_EQ, std::move(wire_id), std::move(arg)) : + std::make_unique(AST_ASSIGN_EQ, std::move(arg), std::move(wire_id)); assign->children[0]->was_checked = true; if (child->is_input) - new_stmts.push_back(assign); + new_stmts.push_back(std::move(assign)); else - output_assignments.push_back(assign); + output_assignments.push_back(std::move(assign)); } } - for (auto child : decl->children) + for (auto& child : decl->children) if (child->type != AST_WIRE && child->type != AST_MEMORY && child->type != AST_PARAMETER && child->type != AST_LOCALPARAM) new_stmts.push_back(child->clone()); - new_stmts.insert(new_stmts.end(), output_assignments.begin(), output_assignments.end()); + new_stmts.reserve(new_stmts.size() + output_assignments.size()); + std::move(output_assignments.begin(), output_assignments.end(), std::back_inserter(new_stmts)); for (auto it = current_block->children.begin(); ; it++) { log_assert(it != current_block->children.end()); - if (*it == current_block_child) { - current_block->children.insert(it, new_stmts.begin(), new_stmts.end()); + if (it->get() == current_block_child) { + current_block->children.insert(it, + std::make_move_iterator(new_stmts.begin()), + std::make_move_iterator(new_stmts.end())); break; } } replace_fcall_with_id: - delete decl; if (type == AST_FCALL) { delete_children(); type = AST_IDENTIFIER; @@ -4243,14 +4210,14 @@ replace_fcall_later:; if (0) { case AST_SHIFT_RIGHT: const_func = RTLIL::const_shr; } if (0) { case AST_SHIFT_SLEFT: const_func = RTLIL::const_sshl; } if (0) { case AST_SHIFT_SRIGHT: const_func = RTLIL::const_sshr; } - if (0) { case AST_POW: const_func = RTLIL::const_pow; } + if (0) { case AST_POW: const_func = RTLIL::const_pow; } if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) { RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint), RTLIL::Const(children[1]->bits), sign_hint, type == AST_POW ? children[1]->is_signed : false, width_hint); newNode = mkconst_bits(y.to_bits(), sign_hint); } else if (type == AST_POW && children[0]->isConst() && children[1]->isConst()) { - newNode = new AstNode(AST_REALVALUE); + newNode = std::make_unique(AST_REALVALUE); newNode->realvalue = pow(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint)); } break; @@ -4295,7 +4262,7 @@ replace_fcall_later:; newNode = mkconst_bits(y.to_bits(), sign_hint); } else if (children[0]->isConst() && children[1]->isConst()) { - newNode = new AstNode(AST_REALVALUE); + newNode = std::make_unique(AST_REALVALUE); switch (type) { case AST_ADD: newNode->realvalue = children[0]->asReal(sign_hint) + children[1]->asReal(sign_hint); break; case AST_SUB: newNode->realvalue = children[0]->asReal(sign_hint) - children[1]->asReal(sign_hint); break; @@ -4314,7 +4281,7 @@ replace_fcall_later:; newNode = mkconst_bits(y.to_bits(), sign_hint); } else if (children[0]->isConst()) { - newNode = new AstNode(AST_REALVALUE); + newNode = std::make_unique(AST_REALVALUE); if (type == AST_NEG) newNode->realvalue = -children[0]->asReal(sign_hint); else @@ -4328,13 +4295,13 @@ replace_fcall_later:; AstNode *choice = pair.first; AstNode *not_choice = pair.second; - if (choice != NULL) { + if (choice != nullptr) { if (choice->type == AST_CONSTANT) { int other_width_hint = width_hint; bool other_sign_hint = sign_hint, other_real = false; not_choice->detectSignWidth(other_width_hint, other_sign_hint, &other_real); if (other_real) { - newNode = new AstNode(AST_REALVALUE); + newNode = std::make_unique(AST_REALVALUE); choice->detectSignWidth(width_hint, sign_hint); newNode->realvalue = choice->asReal(sign_hint); } else { @@ -4357,7 +4324,7 @@ replace_fcall_later:; a.bits()[i] = RTLIL::State::Sx; newNode = mkconst_bits(a.to_bits(), sign_hint); } else if (children[1]->isConst() && children[2]->isConst()) { - newNode = new AstNode(AST_REALVALUE); + newNode = std::make_unique(AST_REALVALUE); if (children[1]->asReal(sign_hint) == children[2]->asReal(sign_hint)) newNode->realvalue = children[1]->asReal(sign_hint); else @@ -4409,12 +4376,12 @@ apply_newNode: // fprintf(stderr, "----\n"); // dumpAst(stderr, "- "); // newNode->dumpAst(stderr, "+ "); - log_assert(newNode != NULL); + log_assert(newNode != nullptr); + // newNode->null_check(); newNode->filename = filename; newNode->location = location; - newNode->cloneInto(this); + newNode->cloneInto(*this); fixup_hierarchy_flags(); - delete newNode; did_something = true; } @@ -4427,21 +4394,21 @@ apply_newNode: void AstNode::replace_result_wire_name_in_function(const std::string &from, const std::string &to) { - for (AstNode *child : children) + for (auto& child : children) child->replace_result_wire_name_in_function(from, to); if (str == from && type != AST_FCALL && type != AST_TCALL) str = to; } // replace a readmem[bh] TCALL ast node with a block of memory assignments -AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init) +std::unique_ptr AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init) { int mem_width, mem_size, addr_bits; memory->meminfo(mem_width, mem_size, addr_bits); - AstNode *block = new AstNode(AST_BLOCK); + auto block = std::make_unique(AST_BLOCK); - AstNode *meminit = nullptr; + AstNode* meminit = nullptr; int next_meminit_cursor=0; vector meminit_bits; vector en_bits; @@ -4515,7 +4482,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m continue; } - AstNode *value = VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width, is_readmemh ? 'h' : 'b') + token); + auto value = VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width, is_readmemh ? 'h' : 'b') + token); if (unconditional_init) { @@ -4526,7 +4493,8 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m meminit->children[3] = AstNode::mkconst_int(meminit_size, false); } - meminit = new AstNode(AST_MEMINIT); + auto meminit_owned = std::make_unique(AST_MEMINIT); + meminit = meminit_owned.get(); meminit->children.push_back(AstNode::mkconst_int(cursor, false)); meminit->children.push_back(nullptr); meminit->children.push_back(AstNode::mkconst_bits(en_bits, false)); @@ -4536,18 +4504,17 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m meminit_bits.clear(); meminit_size = 0; - current_ast_mod->children.push_back(meminit); + current_ast_mod->children.push_back(std::move(meminit_owned)); next_meminit_cursor = cursor; } meminit_size++; next_meminit_cursor++; meminit_bits.insert(meminit_bits.end(), value->bits.begin(), value->bits.end()); - delete value; } else { - block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value)); + block->children.push_back(std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER, std::make_unique(AST_RANGE, AstNode::mkconst_int(cursor, false))), std::move(value))); block->children.back()->children[0]->str = memory->str; block->children.back()->children[0]->id2ast = memory; block->children.back()->children[0]->was_checked = true; @@ -4624,7 +4591,7 @@ void AstNode::expand_genblock(const std::string &prefix) }; for (size_t i = 0; i < children.size(); i++) { - AstNode *child = children[i]; + auto* child = children[i].get(); switch (child->type) { case AST_WIRE: @@ -4650,9 +4617,9 @@ void AstNode::expand_genblock(const std::string &prefix) case AST_ENUM: current_scope[child->str] = child; - for (auto enode : child->children){ + for (auto& enode : child->children){ log_assert(enode->type == AST_ENUM_ITEM); - prefix_node(enode); + prefix_node(enode.get()); } break; @@ -4662,7 +4629,7 @@ void AstNode::expand_genblock(const std::string &prefix) } for (size_t i = 0; i < children.size(); i++) { - AstNode *child = children[i]; + auto& child = children[i]; // AST_PREFIX member names should not be prefixed; we recurse into them // as normal to ensure indices and ranges are properly resolved, and // then restore the previous string @@ -4694,7 +4661,7 @@ void AstNode::label_genblks(std::set& existing, int &counter) // seeing a proper generate control flow construct increments the // counter once ++counter; - for (AstNode *child : children) + for (auto& child : children) child->label_genblks(existing, counter); break; @@ -4711,7 +4678,7 @@ void AstNode::label_genblks(std::set& existing, int &counter) // within a genblk, the counter starts fresh std::set existing_local = existing; int counter_local = 0; - for (AstNode *child : children) + for (auto& child : children) child->label_genblks(existing_local, counter_local); break; } @@ -4720,7 +4687,7 @@ void AstNode::label_genblks(std::set& existing, int &counter) // track names which could conflict with implicit genblk names if (str.rfind("\\genblk", 0) == 0) existing.insert(str); - for (AstNode *child : children) + for (auto& child : children) child->label_genblks(existing, counter); break; } @@ -4731,7 +4698,7 @@ static void mark_memories_assign_lhs_complex(dict> & dict &mem2reg_candidates, AstNode *that) { for (auto &child : that->children) - mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, child); + mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, child.get()); if (that->type == AST_IDENTIFIER && that->id2ast && that->id2ast->type == AST_MEMORY) { AstNode *mem = that->id2ast; @@ -4755,7 +4722,7 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg { // mark all memories that are used in a complex expression on the left side of an assignment for (auto &lhs_child : children[0]->children) - mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, lhs_child); + mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, lhs_child.get()); if (children[0]->type == AST_IDENTIFIER && children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY) { @@ -4821,11 +4788,11 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg if ((type == AST_MODULE || type == AST_INTERFACE) && get_bool_attribute(ID::mem2reg)) children_flags |= AstNode::MEM2REG_FL_ALL; - dict *proc_flags_p = NULL; + dict *proc_flags_p = nullptr; if (type == AST_ALWAYS) { int count_edge_events = 0; - for (auto child : children) + for (auto& child : children) if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) count_edge_events++; if (count_edge_events != 1) @@ -4841,12 +4808,12 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg flags |= children_flags; log_assert((flags & ~0x000000ff) == 0); - for (auto child : children) + for (auto& child : children) { if (lhs_children_counter > 0) { lhs_children_counter--; if (child->children.size() && child->children[0]->type == AST_RANGE && child->children[0]->children.size()) { - for (auto c : child->children[0]->children) { + for (auto& c : child->children[0]->children) { if (proc_flags_p) c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags); else @@ -4882,7 +4849,7 @@ bool AstNode::mem2reg_check(pool &mem2reg_set) return true; } -void AstNode::mem2reg_remove(pool &mem2reg_set, vector &delnodes) +void AstNode::mem2reg_remove(pool &mem2reg_set) { log_assert(mem2reg_set.count(this) == 0); @@ -4890,17 +4857,16 @@ void AstNode::mem2reg_remove(pool &mem2reg_set, vector &deln id2ast = nullptr; for (size_t i = 0; i < children.size(); i++) { - if (mem2reg_set.count(children[i]) > 0) { - delnodes.push_back(children[i]); + if (mem2reg_set.count(children[i].get()) > 0) { children.erase(children.begin() + (i--)); } else { - children[i]->mem2reg_remove(mem2reg_set, delnodes); + children[i]->mem2reg_remove(mem2reg_set); } } } // actually replace memories with registers -bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block) +bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *block, AstNode* async_block) { bool did_something = false; @@ -4927,9 +4893,10 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, if (length != 0) { - AstNode *block = new AstNode(AST_INITIAL, new AstNode(AST_BLOCK)); - mod->children.push_back(block); - block = block->children[0]; + auto block_owned = std::make_unique(AST_INITIAL, std::make_unique(AST_BLOCK)); + auto block = block_owned.get(); + mod->children.push_back(std::move(block_owned)); + block = block->children[0].get(); int wordsz = GetSize(data) / length; @@ -4943,11 +4910,11 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, while (epos < wordsz && en[epos] == State::S1) epos++; int clen = epos - pos; - AstNode *range = new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false)); + auto range = std::make_unique(AST_RANGE, AstNode::mkconst_int(cursor+i, false)); if (pos != 0 || epos != wordsz) { int left; int right; - AstNode *mrange = id2ast->children[0]; + auto& mrange = id2ast->children[0]; if (mrange->range_left < mrange->range_right) { right = mrange->range_right - pos; left = mrange->range_right - epos + 1; @@ -4955,42 +4922,39 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, right = mrange->range_right + pos; left = mrange->range_right + epos - 1; } - range = new AstNode(AST_MULTIRANGE, range, new AstNode(AST_RANGE, AstNode::mkconst_int(left, true), AstNode::mkconst_int(right, true))); + range = std::make_unique(AST_MULTIRANGE, std::move(range), std::make_unique(AST_RANGE, AstNode::mkconst_int(left, true), AstNode::mkconst_int(right, true))); } - AstNode *target = new AstNode(AST_IDENTIFIER, range); + auto target = std::make_unique(AST_IDENTIFIER, std::move(range)); target->str = str; target->id2ast = id2ast; target->was_checked = true; - block->children.push_back(new AstNode(AST_ASSIGN_EQ, target, mkconst_bits(data.extract(i*wordsz + pos, clen).to_bits(), false))); + block->children.push_back(std::make_unique(AST_ASSIGN_EQ, std::move(target), mkconst_bits(data.extract(i*wordsz + pos, clen).to_bits(), false))); pos = epos; } } } } - AstNode *newNode = new AstNode(AST_NONE); - newNode->cloneInto(this); - delete newNode; - + auto newNode = std::make_unique(AST_NONE); + newNode->cloneInto(*this); did_something = true; } - if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set)) + if (type == AST_ASSIGN && block == nullptr && children[0]->mem2reg_check(mem2reg_set)) { - if (async_block == NULL) { - async_block = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK)); - mod->children.push_back(async_block); + if (async_block == nullptr) { + auto async_block_owned = std::make_unique(AST_ALWAYS, std::make_unique(AST_BLOCK)); + async_block = async_block_owned.get(); + mod->children.push_back(std::move(async_block_owned)); } - AstNode *newNode = clone(); + auto newNode = clone(); newNode->type = AST_ASSIGN_EQ; newNode->children[0]->was_checked = true; - async_block->children[0]->children.push_back(newNode); - - newNode = new AstNode(AST_NONE); - newNode->cloneInto(this); - delete newNode; + async_block->children[0]->children.push_back(std::move(newNode)); + newNode = std::make_unique(AST_NONE); + newNode->cloneInto(*this); did_something = true; } @@ -5005,57 +4969,57 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, bool mem_signed = children[0]->id2ast->is_signed; children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); - AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); + auto wire_addr = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); wire_addr->str = id_addr; wire_addr->is_reg = true; wire_addr->was_checked = true; wire_addr->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); - mod->children.push_back(wire_addr); while (wire_addr->simplify(true, 1, -1, false)) { } + mod->children.push_back(std::move(wire_addr)); - AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); + auto wire_data = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); wire_data->str = id_data; wire_data->is_reg = true; wire_data->was_checked = true; wire_data->is_signed = mem_signed; wire_data->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); - mod->children.push_back(wire_data); while (wire_data->simplify(true, 1, -1, false)) { } + mod->children.push_back(std::move(wire_data)); - log_assert(block != NULL); + log_assert(block != nullptr); size_t assign_idx = 0; - while (assign_idx < block->children.size() && block->children[assign_idx] != this) + while (assign_idx < block->children.size() && block->children[assign_idx].get() != this) assign_idx++; log_assert(assign_idx < block->children.size()); - AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); + auto assign_addr = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); assign_addr->children[0]->str = id_addr; assign_addr->children[0]->was_checked = true; - block->children.insert(block->children.begin()+assign_idx+1, assign_addr); + block->children.insert(block->children.begin()+assign_idx+1, std::move(assign_addr)); - AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER)); + auto case_node = std::make_unique(AST_CASE, std::make_unique(AST_IDENTIFIER)); case_node->children[0]->str = id_addr; for (int i = 0; i < mem_size; i++) { if (children[0]->children[0]->children[0]->type == AST_CONSTANT && int(children[0]->children[0]->children[0]->integer) != i) continue; - AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK)); - AstNode *assign_reg = new AstNode(type, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER)); + auto cond_node = std::make_unique(AST_COND, AstNode::mkconst_int(i, false, addr_bits), std::make_unique(AST_BLOCK)); + auto assign_reg = std::make_unique(type, std::make_unique(AST_IDENTIFIER), std::make_unique(AST_IDENTIFIER)); if (children[0]->children.size() == 2) assign_reg->children[0]->children.push_back(children[0]->children[1]->clone()); assign_reg->children[0]->str = stringf("%s[%d]", children[0]->str.c_str(), i); assign_reg->children[1]->str = id_data; - cond_node->children[1]->children.push_back(assign_reg); - case_node->children.push_back(cond_node); + cond_node->children[1]->children.push_back(std::move(assign_reg)); + case_node->children.push_back(std::move(cond_node)); } // fixup on the full hierarchy below case_node case_node->fixup_hierarchy_flags(true); - block->children.insert(block->children.begin()+assign_idx+2, case_node); + block->children.insert(block->children.begin()+assign_idx+2, std::move(case_node)); children[0]->delete_children(); children[0]->range_valid = false; - children[0]->id2ast = NULL; + children[0]->id2ast = nullptr; children[0]->str = id_data; type = AST_ASSIGN_EQ; children[0]->was_checked = true; @@ -5066,7 +5030,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, if (mem2reg_check(mem2reg_set)) { - AstNode *bit_part_sel = NULL; + std::unique_ptr bit_part_sel = nullptr; if (children.size() == 2) bit_part_sel = children[1]->clone(); @@ -5083,7 +5047,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, str = stringf("%s[%d]", str.c_str(), id); delete_children(); range_valid = false; - id2ast = NULL; + id2ast = nullptr; } else { @@ -5096,7 +5060,6 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, else width = bit_part_sel->children[0]->integer - bit_part_sel->children[1]->integer; - delete bit_part_sel; bit_part_sel = nullptr; } else @@ -5111,9 +5074,8 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, std::vector x_bits; for (int i = 0; i < width; i++) x_bits.push_back(RTLIL::State::Sx); - AstNode *constant = AstNode::mkconst_bits(x_bits, false); - constant->cloneInto(this); - delete constant; + std::unique_ptr constant = AstNode::mkconst_bits(x_bits, false); + constant->cloneInto(*this); } } else @@ -5126,54 +5088,54 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, bool mem_signed = id2ast->is_signed; id2ast->meminfo(mem_width, mem_size, addr_bits); - AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); + auto wire_addr = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); wire_addr->str = id_addr; wire_addr->is_reg = true; wire_addr->was_checked = true; if (block) wire_addr->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); - mod->children.push_back(wire_addr); while (wire_addr->simplify(true, 1, -1, false)) { } + mod->children.push_back(std::move(wire_addr)); - AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); + auto wire_data = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); wire_data->str = id_data; wire_data->is_reg = true; wire_data->was_checked = true; wire_data->is_signed = mem_signed; if (block) wire_data->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); - mod->children.push_back(wire_data); while (wire_data->simplify(true, 1, -1, false)) { } + mod->children.push_back(std::move(wire_data)); - AstNode *assign_addr = new AstNode(block ? AST_ASSIGN_EQ : AST_ASSIGN, new AstNode(AST_IDENTIFIER), children[0]->children[0]->clone()); + auto assign_addr = std::make_unique(block ? AST_ASSIGN_EQ : AST_ASSIGN, std::make_unique(AST_IDENTIFIER), children[0]->children[0]->clone()); assign_addr->children[0]->str = id_addr; assign_addr->children[0]->was_checked = true; - AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER)); + auto case_node = std::make_unique(AST_CASE, std::make_unique(AST_IDENTIFIER)); case_node->children[0]->str = id_addr; for (int i = 0; i < mem_size; i++) { if (children[0]->children[0]->type == AST_CONSTANT && int(children[0]->children[0]->integer) != i) continue; - AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK)); - AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER)); + auto cond_node = std::make_unique(AST_COND, AstNode::mkconst_int(i, false, addr_bits), std::make_unique(AST_BLOCK)); + auto assign_reg = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), std::make_unique(AST_IDENTIFIER)); assign_reg->children[0]->str = id_data; assign_reg->children[0]->was_checked = true; assign_reg->children[1]->str = stringf("%s[%d]", str.c_str(), i); - cond_node->children[1]->children.push_back(assign_reg); - case_node->children.push_back(cond_node); + cond_node->children[1]->children.push_back(std::move(assign_reg)); + case_node->children.push_back(std::move(cond_node)); } std::vector x_bits; for (int i = 0; i < mem_width; i++) x_bits.push_back(RTLIL::State::Sx); - AstNode *cond_node = new AstNode(AST_COND, new AstNode(AST_DEFAULT), new AstNode(AST_BLOCK)); - AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false)); + auto cond_node = std::make_unique(AST_COND, std::make_unique(AST_DEFAULT), std::make_unique(AST_BLOCK)); + auto assign_reg = std::make_unique(AST_ASSIGN_EQ, std::make_unique(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false)); assign_reg->children[0]->str = id_data; assign_reg->children[0]->was_checked = true; - cond_node->children[1]->children.push_back(assign_reg); - case_node->children.push_back(cond_node); + cond_node->children[1]->children.push_back(std::move(assign_reg)); + case_node->children.push_back(std::move(cond_node)); // fixup on the full hierarchy below case_node case_node->fixup_hierarchy_flags(true); @@ -5184,34 +5146,37 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, while (assign_idx < block->children.size() && !block->children[assign_idx]->contains(this)) assign_idx++; log_assert(assign_idx < block->children.size()); - block->children.insert(block->children.begin()+assign_idx, case_node); - block->children.insert(block->children.begin()+assign_idx, assign_addr); + block->children.insert(block->children.begin()+assign_idx, std::move(case_node)); + block->children.insert(block->children.begin()+assign_idx, std::move(assign_addr)); } else { - AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK, case_node)); - mod->children.push_back(proc); - mod->children.push_back(assign_addr); + auto proc = std::make_unique(AST_ALWAYS, std::make_unique(AST_BLOCK, std::move(case_node))); + mod->children.push_back(std::move(proc)); + mod->children.push_back(std::move(assign_addr)); mod->fixup_hierarchy_flags(); } delete_children(); range_valid = false; - id2ast = NULL; + id2ast = nullptr; str = id_data; } if (bit_part_sel) { - children.push_back(bit_part_sel); + children.push_back(std::move(bit_part_sel)); fixup_hierarchy_flags(); } did_something = true; } - log_assert(id2ast == NULL || mem2reg_set.count(id2ast) == 0); + log_assert(id2ast == nullptr || mem2reg_set.count(id2ast) == 0); + + std::vector children_list; + for (auto& child : children) + children_list.push_back(child.get()); - auto children_list = children; for (size_t i = 0; i < children_list.size(); i++) if (children_list[i]->mem2reg_as_needed_pass2(mem2reg_set, mod, block, async_block)) did_something = true; @@ -5296,7 +5261,7 @@ bool AstNode::has_const_only_constructs() { if (type == AST_WHILE || type == AST_REPEAT) return true; - for (auto child : children) + for (auto& child : children) if (child->has_const_only_constructs()) return true; return false; @@ -5306,7 +5271,7 @@ bool AstNode::is_simple_const_expr() { if (type == AST_IDENTIFIER) return false; - for (auto child : children) + for (auto& child : children) if (!child->is_simple_const_expr()) return false; return true; @@ -5341,9 +5306,8 @@ bool AstNode::replace_variables(std::map &varia offset = -offset; std::vector &var_bits = variables.at(str).val.bits(); std::vector new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width); - AstNode *newNode = mkconst_bits(new_bits, variables.at(str).is_signed); - newNode->cloneInto(this); - delete newNode; + auto newNode = mkconst_bits(new_bits, variables.at(str).is_signed); + newNode->cloneInto(*this); return true; } @@ -5354,32 +5318,34 @@ bool AstNode::replace_variables(std::map &varia } // attempt to statically evaluate a functions with all-const arguments -AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) +std::unique_ptr AstNode::eval_const_function(AstNode *fcall, bool must_succeed) { std::map backup_scope = current_scope; std::map variables; - std::vector to_delete; - AstNode *block = new AstNode(AST_BLOCK); - AstNode *result = nullptr; + auto block = std::make_unique(AST_BLOCK); + std::unique_ptr result = nullptr; size_t argidx = 0; - for (auto child : children) + for (auto& child : children) { block->children.push_back(child->clone()); } block->set_in_param_flag(true); + std::vector> temporary_nodes; while (!block->children.empty()) { - AstNode *stmt = block->children.front(); + // log("%zu left in block %p\n", block->children.size(), block.get()); + std::unique_ptr& stmt = block->children.front(); #if 0 log("-----------------------------------\n"); for (auto &it : variables) log("%20s %40s\n", it.first.c_str(), log_signal(it.second.val)); - stmt->dumpAst(NULL, "stmt> "); + stmt->dumpAst(nullptr, "stmt> "); #endif - + // log("A\n"); + // log("%s\n", type2str(stmt->type).c_str()); if (stmt->type == AST_WIRE) { while (stmt->simplify(true, 1, -1, false)) { } @@ -5404,7 +5370,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) stmt->children.back()->type == AST_RANGE; // identify the argument corresponding to this wire, if applicable if (stmt->is_input && argidx < fcall->children.size()) { - variable.arg = fcall->children.at(argidx++); + variable.arg = fcall->children.at(argidx++).get(); } // load the constant arg's value into this variable if (variable.arg) { @@ -5415,10 +5381,10 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) variable.val = variable.arg->realAsConst(width); } } - current_scope[stmt->str] = stmt; + current_scope[stmt->str] = stmt.get(); + temporary_nodes.push_back(std::move(stmt)); block->children.erase(block->children.begin()); - to_delete.push_back(stmt); continue; } @@ -5428,10 +5394,10 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) { while (stmt->simplify(true, 1, -1, false)) { } - current_scope[stmt->str] = stmt; + current_scope[stmt->str] = stmt.get(); + temporary_nodes.push_back(std::move(stmt)); block->children.erase(block->children.begin()); - to_delete.push_back(stmt); continue; } @@ -5472,7 +5438,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) if (stmt->children.at(0)->children.empty()) { variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.size()); } else { - AstNode *range = stmt->children.at(0)->children.at(0); + AstNode *range = stmt->children.at(0)->children.at(0).get(); if (!range->range_valid) { if (!must_succeed) goto finished; @@ -5490,24 +5456,28 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) } } - delete block->children.front(); block->children.erase(block->children.begin()); continue; } if (stmt->type == AST_FOR) { - block->children.insert(block->children.begin(), stmt->children.at(0)); - stmt->children.at(3)->children.push_back(stmt->children.at(2)); + stmt->type = AST_WHILE; + log_assert(stmt->children.size() > 2); + auto yoink0 = std::move(stmt->children.at(0)); + log_assert(stmt->children.size() > 2); + auto yoink2 = std::move(stmt->children.at(2)); + stmt->children.at(3)->children.push_back(std::move(yoink2)); stmt->children.erase(stmt->children.begin() + 2); stmt->children.erase(stmt->children.begin()); - stmt->type = AST_WHILE; + block->children.insert(block->children.begin(), std::move(yoink0)); + log_assert(stmt->children.size() == 2); continue; } if (stmt->type == AST_WHILE) { - AstNode *cond = stmt->children.at(0)->clone(); + auto cond = stmt->children.at(0)->clone(); if (!cond->replace_variables(variables, fcall, must_succeed)) goto finished; cond->set_in_param_flag(true); @@ -5523,17 +5493,14 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) if (cond->asBool()) { block->children.insert(block->children.begin(), stmt->children.at(1)->clone()); } else { - delete block->children.front(); block->children.erase(block->children.begin()); } - - delete cond; continue; } if (stmt->type == AST_REPEAT) { - AstNode *num = stmt->children.at(0)->clone(); + auto num = stmt->children.at(0)->clone(); if (!num->replace_variables(variables, fcall, must_succeed)) goto finished; num->set_in_param_flag(true); @@ -5546,41 +5513,41 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) fcall->loc_string().c_str()); } + temporary_nodes.push_back(std::move(stmt)); block->children.erase(block->children.begin()); for (int i = 0; i < num->bitsAsConst().as_int(); i++) - block->children.insert(block->children.begin(), stmt->children.at(1)->clone()); + block->children.insert(block->children.begin(), temporary_nodes.back()->children.at(1)->clone()); - delete stmt; - delete num; continue; } if (stmt->type == AST_CASE) { - AstNode *expr = stmt->children.at(0)->clone(); + auto expr = stmt->children.at(0)->clone(); if (!expr->replace_variables(variables, fcall, must_succeed)) goto finished; expr->set_in_param_flag(true); while (expr->simplify(true, 1, -1, false)) { } - AstNode *sel_case = NULL; + AstNode *sel_case = nullptr; + std::unique_ptr sel_case_copy = nullptr; for (size_t i = 1; i < stmt->children.size(); i++) { bool found_match = false; log_assert(stmt->children.at(i)->type == AST_COND || stmt->children.at(i)->type == AST_CONDX || stmt->children.at(i)->type == AST_CONDZ); if (stmt->children.at(i)->children.front()->type == AST_DEFAULT) { - sel_case = stmt->children.at(i)->children.back(); + sel_case = stmt->children.at(i)->children.back().get(); continue; } for (size_t j = 0; j+1 < stmt->children.at(i)->children.size() && !found_match; j++) { - AstNode *cond = stmt->children.at(i)->children.at(j)->clone(); + auto cond = stmt->children.at(i)->children.at(j)->clone(); if (!cond->replace_variables(variables, fcall, must_succeed)) goto finished; - cond = new AstNode(AST_EQ, expr->clone(), cond); + cond = std::make_unique(AST_EQ, expr->clone(), std::move(cond)); cond->set_in_param_flag(true); while (cond->simplify(true, 1, -1, false)) { } @@ -5592,20 +5559,19 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) } found_match = cond->asBool(); - delete cond; } if (found_match) { - sel_case = stmt->children.at(i)->children.back(); + sel_case = stmt->children.at(i)->children.back().get(); break; } } + if (sel_case) + sel_case_copy = sel_case->clone(); block->children.erase(block->children.begin()); - if (sel_case) - block->children.insert(block->children.begin(), sel_case->clone()); - delete stmt; - delete expr; + if (sel_case_copy) + block->children.insert(block->children.begin(), std::move(sel_case_copy)); continue; } @@ -5613,15 +5579,19 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) { if (!stmt->str.empty()) stmt->expand_genblock(stmt->str + "."); - + auto* stmt_leaky = stmt.get(); + temporary_nodes.push_back(std::move(stmt)); block->children.erase(block->children.begin()); - block->children.insert(block->children.begin(), stmt->children.begin(), stmt->children.end()); - stmt->children.clear(); + block->children.reserve(block->children.size() + stmt_leaky->children.size()); + block->children.insert(block->children.begin(), + std::make_move_iterator(stmt_leaky->children.begin()), + std::make_move_iterator(stmt_leaky->children.end())); + stmt_leaky->children.clear(); block->fixup_hierarchy_flags(); - delete stmt; continue; } + // log("C\n"); if (!must_succeed) goto finished; stmt->input_error("Unsupported language construct in constant function\n%s: ... called from here.\n", @@ -5632,14 +5602,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) result = AstNode::mkconst_bits(variables.at(str).val.to_bits(), variables.at(str).is_signed); finished: - delete block; current_scope = backup_scope; - - for (auto it : to_delete) { - delete it; - } - to_delete.clear(); - return result; } @@ -5650,14 +5613,13 @@ void AstNode::allocateDefaultEnumValues() if (children.front()->attributes.count(ID::enum_base_type)) return; // already elaborated int last_enum_int = -1; - for (auto node : children) { + for (auto& node : children) { log_assert(node->type==AST_ENUM_ITEM); node->set_attribute(ID::enum_base_type, mkconst_str(str)); for (size_t i = 0; i < node->children.size(); i++) { switch (node->children[i]->type) { case AST_NONE: // replace with auto-incremented constant - delete node->children[i]; node->children[i] = AstNode::mkconst_int(++last_enum_int, true); break; case AST_CONSTANT: @@ -5686,8 +5648,8 @@ bool AstNode::is_recursive_function() const if (it != current_scope.end() && visit(it->second)) return true; } - for (const AstNode *child : node->children) { - if (visit(child)) + for (auto& child : node->children) { + if (visit(child.get())) return true; } return false; @@ -5717,9 +5679,9 @@ std::pair AstNode::get_tern_choice() AstNode *choice = nullptr, *not_choice = nullptr; if (found_sure_true) - choice = children[1], not_choice = children[2]; + choice = children[1].get(), not_choice = children[2].get(); else if (!found_maybe_true) - choice = children[2], not_choice = children[1]; + choice = children[2].get(), not_choice = children[1].get(); return {choice, not_choice}; } diff --git a/frontends/verilog/.gitignore b/frontends/verilog/.gitignore index aadbcdcdd..a6d4c8b86 100644 --- a/frontends/verilog/.gitignore +++ b/frontends/verilog/.gitignore @@ -2,3 +2,6 @@ verilog_lexer.cc verilog_parser.output verilog_parser.tab.cc verilog_parser.tab.hh +position.hh +location.hh +stack.hh diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc index 2c923f0b7..2d26f1930 100644 --- a/frontends/verilog/Makefile.inc +++ b/frontends/verilog/Makefile.inc @@ -9,6 +9,7 @@ frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y $(P) $(BISON) -Wall -Werror -o $@ -d -r all -b frontends/verilog/verilog_parser $< frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc +frontends/verilog/verilog_frontend.h: frontends/verilog/verilog_parser.tab.hh frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l frontends/verilog/verilog_parser.tab.cc $(Q) mkdir -p $(dir $@) diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index a4dfbc7ec..1f5f437ef 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -43,6 +43,10 @@ YOSYS_NAMESPACE_BEGIN using namespace AST; +static int get_line_num() { + // TODO + return 999; +} // divide an arbitrary length decimal number by two and return the rest static int my_decimal_div_by_two(std::vector &digits) { @@ -148,10 +152,10 @@ static void my_strtobin(std::vector &data, const char *str, int le } // convert the Verilog code for a constant to an AST node -AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn_z) +std::unique_ptr VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn_z) { if (warn_z) { - AstNode *ret = const2ast(code, case_type); + auto ret = const2ast(code, case_type); if (ret != nullptr && std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end()) log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n", current_filename.c_str(), get_line_num()); @@ -172,7 +176,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn ch = ch >> 1; } } - AstNode *ast = AstNode::mkconst_bits(data, false); + auto ast = AstNode::mkconst_bits(data, false); ast->str = code; return ast; } diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 14a0f16c0..6d4532759 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -48,11 +48,11 @@ static void error_on_dpi_function(AST::AstNode *node) { if (node->type == AST::AST_DPI_FUNCTION) log_file_error(node->filename, node->location.first_line, "Found DPI function %s.\n", node->str.c_str()); - for (auto child : node->children) - error_on_dpi_function(child); + for (auto& child : node->children) + error_on_dpi_function(child.get()); } -static void add_package_types(dict &user_types, std::vector &package_list) +static void add_package_types(dict &user_types, std::vector> &package_list) { // prime the parser's user type lookup table with the package qualified names // of typedefed names in the packages seen so far. @@ -61,14 +61,16 @@ static void add_package_types(dict &user_types, std for (const auto &node: pkg->children) { if (node->type == AST::AST_TYPEDEF) { std::string s = pkg->str + "::" + node->str.substr(1); - user_types[s] = node; + user_types[s] = node.get(); } } } } struct VerilogFrontend : public Frontend { - VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { } + VerilogLexer lexer; + frontend_verilog_yy::parser parser; + VerilogFrontend() : Frontend("verilog", "read modules from Verilog file"), lexer(), parser(&lexer) { } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -266,12 +268,14 @@ struct VerilogFrontend : public Frontend { bool flag_noblackbox = false; bool flag_nowb = false; bool flag_nosynthesis = false; + bool flag_yydebug = false; define_map_t defines_map; std::list include_dirs; std::list attributes; - frontend_verilog_yydebug = false; + lexer.set_debug(false); + parser.set_debug_level(0); sv_mode = false; formal_mode = false; noassert_mode = false; @@ -329,7 +333,8 @@ struct VerilogFrontend : public Frontend { flag_dump_ast2 = true; flag_dump_vlog1 = true; flag_dump_vlog2 = true; - frontend_verilog_yydebug = true; + lexer.set_debug(true); + parser.set_debug_level(1); continue; } if (arg == "-dump_ast1") { @@ -357,7 +362,7 @@ struct VerilogFrontend : public Frontend { continue; } if (arg == "-yydebug") { - frontend_verilog_yydebug = true; + flag_yydebug = true; continue; } if (arg == "-nolatches") { @@ -480,8 +485,6 @@ struct VerilogFrontend : public Frontend { formal_mode ? "formal " : "", sv_mode ? "SystemVerilog" : "Verilog", filename.c_str()); AST::current_filename = filename; - AST::set_line_num = &frontend_verilog_yyset_lineno; - AST::get_line_num = &frontend_verilog_yyget_lineno; current_ast = new AST::AstNode(AST::AST_DESIGN); @@ -499,9 +502,9 @@ struct VerilogFrontend : public Frontend { add_package_types(pkg_user_types, design->verilog_packages); UserTypeMap global_types_map; - for (auto def : design->verilog_globals) { + for (auto& def : design->verilog_globals) { if (def->type == AST::AST_TYPEDEF) { - global_types_map[def->str] = def; + global_types_map[def->str] = def.get(); } } @@ -511,10 +514,16 @@ struct VerilogFrontend : public Frontend { // add a new empty type map to allow overriding existing global definitions user_type_stack.push_back(UserTypeMap()); - frontend_verilog_yyset_lineno(1); - frontend_verilog_yyrestart(NULL); - frontend_verilog_yyparse(); - frontend_verilog_yylex_destroy(); + parser.~parser(); + lexer.~VerilogLexer(); + new (&lexer) VerilogLexer(); + new (&parser) frontend_verilog_yy::parser(&lexer); + if (flag_yydebug) { + lexer.set_debug(true); + parser.set_debug_level(1); + } + parser.parse(); + // frontend_verilog_yyset_lineno(1); for (auto &child : current_ast->children) { if (child->type == AST::AST_MODULE) @@ -759,10 +768,8 @@ struct VerilogFileList : public Pass { #endif -YOSYS_NAMESPACE_END - // the yyerror function used by bison to report parser errors -void frontend_verilog_yyerror(char const *fmt, ...) +void VERILOG_FRONTEND::frontend_verilog_yyerror(char const *fmt, ...) { va_list ap; char buffer[1024]; @@ -771,7 +778,11 @@ void frontend_verilog_yyerror(char const *fmt, ...) p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap); va_end(ap); p += snprintf(p, buffer + sizeof(buffer) - p, "\n"); - YOSYS_NAMESPACE_PREFIX log_file_error(YOSYS_NAMESPACE_PREFIX AST::current_filename, frontend_verilog_yyget_lineno(), - "%s", buffer); + // TODO fix loc + YOSYS_NAMESPACE_PREFIX log_file_error(YOSYS_NAMESPACE_PREFIX AST::current_filename, 999, + "%s", buffer); exit(1); } + +YOSYS_NAMESPACE_END +std::string fmt(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); \ No newline at end of file diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index 8454e7999..96aa55c2f 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -31,6 +31,18 @@ #include "kernel/yosys.h" #include "frontends/ast/ast.h" + +#if ! defined(yyFlexLexerOnce) +#define yyFlexLexer frontend_verilog_yyFlexLexer +#include +#endif +YOSYS_NAMESPACE_BEGIN +namespace VERILOG_FRONTEND { + class VerilogLexer; +}; +YOSYS_NAMESPACE_END +#include "frontends/verilog/verilog_parser.tab.hh" + #include #include #include @@ -43,7 +55,7 @@ namespace VERILOG_FRONTEND extern struct AST::AstNode *current_ast; // this function converts a Verilog constant to an AST_CONSTANT node - AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false); + std::unique_ptr const2ast(std::string code, char case_type = 0, bool warn_z = false); // names of locally typedef'ed types in a stack typedef std::map UserTypeMap; @@ -84,17 +96,32 @@ namespace VERILOG_FRONTEND // lexer input stream extern std::istream *lexin; -} + using parser = frontend_verilog_yy::parser; + class VerilogLexer : public frontend_verilog_yyFlexLexer { + public: + VerilogLexer(std::istream* in = nullptr) : frontend_verilog_yyFlexLexer(in) {} + ~VerilogLexer() override {} + // autogenerated body due to YY_DECL + parser::symbol_type nextToken(); + // get rid of override virtual function warning + using FlexLexer::yylex; + parser::symbol_type terminate() { + return parser::make_FRONTEND_VERILOG_YYEOF(out_loc); + } + parser::location_type out_loc; + private: + std::vector fn_stack; + std::vector ln_stack; + parser::location_type real_loc; + parser::location_type old_loc; + }; + + extern void frontend_verilog_yyerror(char const *fmt, ...); + // parser::symbol_type frontend_verilog_yylex(VerilogLexer& lexer) { + // return lexer.nextToken(); + // }; +}; YOSYS_NAMESPACE_END -// the usual bison/flex stuff -extern int frontend_verilog_yydebug; -void frontend_verilog_yyerror(char const *fmt, ...); -void frontend_verilog_yyrestart(FILE *f); -int frontend_verilog_yyparse(void); -int frontend_verilog_yylex_destroy(void); -int frontend_verilog_yyget_lineno(void); -void frontend_verilog_yyset_lineno (int); - #endif diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 8a3734302..4a0a1cb9f 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -32,7 +32,16 @@ * */ +%option c++ +%option yyclass="VerilogLexer" +%option noyywrap +%option nounput +%option yylineno +%option prefix="frontend_verilog_yy" + %{ +//%option bison-locations +//%option bison-bridge #ifdef __clang__ // bison generates code using the 'register' storage class specifier @@ -41,85 +50,113 @@ #pragma clang diagnostic ignored "-Wmisleading-indentation" #endif -#include "kernel/log.h" #include "frontends/verilog/verilog_frontend.h" #include "frontends/ast/ast.h" -#include "verilog_parser.tab.hh" +#include "kernel/log.h" +#include USING_YOSYS_NAMESPACE using namespace AST; using namespace VERILOG_FRONTEND; - -#define YYSTYPE FRONTEND_VERILOG_YYSTYPE -#define YYLTYPE FRONTEND_VERILOG_YYLTYPE +using parser = frontend_verilog_yy::parser; +//#define YYSTYPE FRONTEND_VERILOG_YYSTYPE +//#define YYLTYPE FRONTEND_VERILOG_YYLTYPE YOSYS_NAMESPACE_BEGIN -namespace VERILOG_FRONTEND { - std::vector fn_stack; - std::vector ln_stack; - YYLTYPE real_location; - YYLTYPE old_location; -} +#undef YY_DECL +#define YY_DECL parser::symbol_type VerilogLexer::nextToken() + +#undef yyterminate +#define yyterminate() terminate() + YOSYS_NAMESPACE_END #define SV_KEYWORD(_tok) \ if (sv_mode) return _tok; \ log("Lexer warning: The SystemVerilog keyword `%s' (at %s:%d) is not "\ - "recognized unless read_verilog is called with -sv!\n", yytext, \ - AST::current_filename.c_str(), frontend_verilog_yyget_lineno()); \ - yylval->string = new std::string(std::string("\\") + yytext); \ - return TOK_ID; + "recognized unless read_verilog is called with -sv!\n", YYText(), \ + AST::current_filename.c_str(), yylineno); \ + string_t val = new std::string(std::string("\\") + YYText()); \ + return parser::make_TOK_ID(val, out_loc); #define NON_KEYWORD() \ - yylval->string = new std::string(std::string("\\") + yytext); \ - return TOK_ID; + string_t val = new std::string(std::string("\\") + YYText()); \ + return parser::make_TOK_ID(val, out_loc); #define YY_INPUT(buf,result,max_size) \ result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size) #define YY_USER_ACTION \ - old_location = real_location; \ - real_location.first_line = real_location.last_line; \ - real_location.first_column = real_location.last_column; \ - for(int i = 0; yytext[i] != '\0'; ++i){ \ - if(yytext[i] == '\n') { \ - real_location.last_line++; \ - real_location.last_column = 1; \ - } \ - else { \ - real_location.last_column++; \ - } \ - } \ - (*yylloc) = real_location; + old_loc = real_loc; \ + real_loc.begin = real_loc.end; \ + for(int i = 0; YYText()[i] != '\0'; ++i){ \ + if(YYText()[i] == '\n') { \ + real_loc.end.line++; \ + real_loc.end.column = 1; \ + } \ + else { \ + real_loc.end.column++; \ + } \ + } #define YY_BREAK \ - (*yylloc) = old_location; \ + out_loc = old_loc; \ break; #undef YY_BUF_SIZE #define YY_BUF_SIZE 65536 -extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param); - static bool isUserType(std::string &s) { // check current scope then outer scopes for a name for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) { if (it->count(s) > 0) { - return true; + return true; } } return false; } -%} +parser::symbol_type char_tok(char c, parser::location_type loc) { + switch (c) { + case '!': return parser::make_TOK_EXCL(loc); + case '#': return parser::make_TOK_HASH(loc); + case '%': return parser::make_TOK_PERC(loc); + case '&': return parser::make_TOK_AMP(loc); + case '(': return parser::make_TOK_LPAREN(loc); + case ')': return parser::make_TOK_RPAREN(loc); + case '*': return parser::make_TOK_ASTER(loc); + case '+': return parser::make_TOK_PLUS(loc); + case ',': return parser::make_TOK_COMMA(loc); + case '-': return parser::make_TOK_MINUS(loc); + case '.': return parser::make_TOK_DOT(loc); + case '/': return parser::make_TOK_SLASH(loc); + case ':': return parser::make_TOK_COL(loc); + case ';': return parser::make_TOK_SEMICOL(loc); + case '<': return parser::make_TOK_LT(loc); + case '=': return parser::make_TOK_EQ(loc); + case '>': return parser::make_TOK_GT(loc); + case '?': return parser::make_TOK_QUE(loc); + case '@': return parser::make_TOK_AT(loc); + case '[': return parser::make_TOK_LBRA(loc); + case ']': return parser::make_TOK_RBRA(loc); + case '^': return parser::make_TOK_CARET(loc); + case '_': return parser::make_TOK_UNDER(loc); + case '{': return parser::make_TOK_LCURL(loc); + case '|': return parser::make_TOK_PIPE(loc); + case '}': return parser::make_TOK_RCURL(loc); + case '~': return parser::make_TOK_TILDE(loc); + case 'n': return parser::make_TOK_n(loc); + case 'p': return parser::make_TOK_p(loc); + case 'x': return parser::make_TOK_x(loc); + case 'z': return parser::make_TOK_z(loc); + case 0: return parser::make_FRONTEND_VERILOG_YYEOF(loc); + default: + std::cout << ".." << +c << "..\n"; return parser::make_ch_t(c, loc); + } +} -%option yylineno -%option noyywrap -%option nounput -%option bison-locations -%option bison-bridge -%option prefix="frontend_verilog_yy" +%} %x COMMENT %x STRING @@ -134,47 +171,48 @@ FIXED_POINT_NUMBER_NO_DEC [0-9][0-9_]*[eE][-+]?[0-9_]+ TIME_SCALE_SUFFIX [munpf]?s %% + // Initialise comment_caller to something to avoid a "maybe undefined" // warning from GCC. int comment_caller = INITIAL; "`file_push "[^\n]* { fn_stack.push_back(current_filename); - ln_stack.push_back(frontend_verilog_yyget_lineno()); - current_filename = yytext+11; + ln_stack.push_back(yylineno); + current_filename = YYText()+11; if (!current_filename.empty() && current_filename.front() == '"') current_filename = current_filename.substr(1); if (!current_filename.empty() && current_filename.back() == '"') current_filename = current_filename.substr(0, current_filename.size()-1); - frontend_verilog_yyset_lineno(0); - yylloc->first_line = yylloc->last_line = 0; - real_location.first_line = real_location.last_line = 0; + yylineno = (0); + out_loc.begin.line = out_loc.end.line = 0; + real_loc.begin.line = real_loc.end.line = 0; } "`file_pop"[^\n]*\n { current_filename = fn_stack.back(); fn_stack.pop_back(); - frontend_verilog_yyset_lineno(ln_stack.back()); - yylloc->first_line = yylloc->last_line = ln_stack.back(); - real_location.first_line = real_location.last_line = ln_stack.back(); + yylineno = (ln_stack.back()); + out_loc.begin.line = out_loc.end.line = ln_stack.back(); + real_loc.begin.line = real_loc.end.line = ln_stack.back(); ln_stack.pop_back(); } "`line"[ \t]+[^ \t\r\n]+[ \t]+\"[^ \r\n]+\"[^\r\n]*\n { - char *p = yytext + 5; + const char *p = YYText() + 5; while (*p == ' ' || *p == '\t') p++; - frontend_verilog_yyset_lineno(atoi(p)); - yylloc->first_line = yylloc->last_line = atoi(p); - real_location.first_line = real_location.last_line = atoi(p); + yylineno = (atoi(p)); + out_loc.begin.line = out_loc.end.line = atoi(p); + real_loc.begin.line = real_loc.end.line = atoi(p); while (*p && *p != ' ' && *p != '\t') p++; while (*p == ' ' || *p == '\t') p++; - char *q = *p ? p + 1 : p; + const char *q = *p ? p + 1 : p; while (*q && *q != '"') q++; current_filename = std::string(p).substr(1, q-p-1); } "`file_notfound "[^\n]* { - log_error("Can't open include file `%s'!\n", yytext + 15); + log_error("Can't open include file `%s'!\n", YYText() + 15); } "`timescale"[ \t]+[^ \t\r\n/]+[ \t]*"/"[ \t]*[^ \t\r\n]* /* ignore timescale directive */ @@ -183,7 +221,7 @@ TIME_SCALE_SUFFIX [munpf]?s "`endcelldefine"[^\n]* /* ignore `endcelldefine */ "`default_nettype"[ \t]+[^ \t\r\n/]+ { - char *p = yytext; + const char *p = YYText(); while (*p != 0 && *p != ' ' && *p != '\t') p++; while (*p == ' ' || *p == '\t') p++; if (!strcmp(p, "none")) @@ -198,149 +236,149 @@ TIME_SCALE_SUFFIX [munpf]?s "`endprotect"[^\n]* /* ignore `endprotect*/ "`"[a-zA-Z_$][a-zA-Z0-9_$]* { - frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext); + frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", YYText()); } -"module" { return TOK_MODULE; } -"endmodule" { return TOK_ENDMODULE; } -"function" { return TOK_FUNCTION; } -"endfunction" { return TOK_ENDFUNCTION; } -"task" { return TOK_TASK; } -"endtask" { return TOK_ENDTASK; } -"specify" { return specify_mode ? TOK_SPECIFY : TOK_IGNORED_SPECIFY; } -"endspecify" { return TOK_ENDSPECIFY; } -"specparam" { return TOK_SPECPARAM; } -"package" { SV_KEYWORD(TOK_PACKAGE); } -"endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); } -"interface" { SV_KEYWORD(TOK_INTERFACE); } -"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); } -"modport" { SV_KEYWORD(TOK_MODPORT); } -"parameter" { return TOK_PARAMETER; } -"localparam" { return TOK_LOCALPARAM; } -"defparam" { return TOK_DEFPARAM; } -"assign" { return TOK_ASSIGN; } -"always" { return TOK_ALWAYS; } -"initial" { return TOK_INITIAL; } -"begin" { return TOK_BEGIN; } -"end" { return TOK_END; } -"if" { return TOK_IF; } -"else" { return TOK_ELSE; } -"for" { return TOK_FOR; } -"posedge" { return TOK_POSEDGE; } -"negedge" { return TOK_NEGEDGE; } -"or" { return TOK_OR; } -"case" { return TOK_CASE; } -"casex" { return TOK_CASEX; } -"casez" { return TOK_CASEZ; } -"endcase" { return TOK_ENDCASE; } -"default" { return TOK_DEFAULT; } -"generate" { return TOK_GENERATE; } -"endgenerate" { return TOK_ENDGENERATE; } -"while" { return TOK_WHILE; } -"repeat" { return TOK_REPEAT; } -"automatic" { return TOK_AUTOMATIC; } +"module" { return parser::make_TOK_MODULE(out_loc); } +"endmodule" { return parser::make_TOK_ENDMODULE(out_loc); } +"function" { return parser::make_TOK_FUNCTION(out_loc); } +"endfunction" { return parser::make_TOK_ENDFUNCTION(out_loc); } +"task" { return parser::make_TOK_TASK(out_loc); } +"endtask" { return parser::make_TOK_ENDTASK(out_loc); } +"specify" { return specify_mode ? parser::make_TOK_SPECIFY(out_loc) : parser::make_TOK_IGNORED_SPECIFY(out_loc); } +"endspecify" { return parser::make_TOK_ENDSPECIFY(out_loc); } +"specparam" { return parser::make_TOK_SPECPARAM(out_loc); } +"package" { SV_KEYWORD(parser::make_TOK_PACKAGE(out_loc)); } +"endpackage" { SV_KEYWORD(parser::make_TOK_ENDPACKAGE(out_loc)); } +"interface" { SV_KEYWORD(parser::make_TOK_INTERFACE(out_loc)); } +"endinterface" { SV_KEYWORD(parser::make_TOK_ENDINTERFACE(out_loc)); } +"modport" { SV_KEYWORD(parser::make_TOK_MODPORT(out_loc)); } +"parameter" { return parser::make_TOK_PARAMETER(out_loc); } +"localparam" { return parser::make_TOK_LOCALPARAM(out_loc); } +"defparam" { return parser::make_TOK_DEFPARAM(out_loc); } +"assign" { return parser::make_TOK_ASSIGN(out_loc); } +"always" { return parser::make_TOK_ALWAYS(out_loc); } +"initial" { return parser::make_TOK_INITIAL(out_loc); } +"begin" { return parser::make_TOK_BEGIN(out_loc); } +"end" { return parser::make_TOK_END(out_loc); } +"if" { return parser::make_TOK_IF(out_loc); } +"else" { return parser::make_TOK_ELSE(out_loc); } +"for" { return parser::make_TOK_FOR(out_loc); } +"posedge" { return parser::make_TOK_POSEDGE(out_loc); } +"negedge" { return parser::make_TOK_NEGEDGE(out_loc); } +"or" { return parser::make_TOK_OR(out_loc); } +"case" { return parser::make_TOK_CASE(out_loc); } +"casex" { return parser::make_TOK_CASEX(out_loc); } +"casez" { return parser::make_TOK_CASEZ(out_loc); } +"endcase" { return parser::make_TOK_ENDCASE(out_loc); } +"default" { return parser::make_TOK_DEFAULT(out_loc); } +"generate" { return parser::make_TOK_GENERATE(out_loc); } +"endgenerate" { return parser::make_TOK_ENDGENERATE(out_loc); } +"while" { return parser::make_TOK_WHILE(out_loc); } +"repeat" { return parser::make_TOK_REPEAT(out_loc); } +"automatic" { return parser::make_TOK_AUTOMATIC(out_loc); } -"unique" { SV_KEYWORD(TOK_UNIQUE); } -"unique0" { SV_KEYWORD(TOK_UNIQUE0); } -"priority" { SV_KEYWORD(TOK_PRIORITY); } +"unique" { SV_KEYWORD(parser::make_TOK_UNIQUE(out_loc)); } +"unique0" { SV_KEYWORD(parser::make_TOK_UNIQUE0(out_loc)); } +"priority" { SV_KEYWORD(parser::make_TOK_PRIORITY(out_loc)); } -"always_comb" { SV_KEYWORD(TOK_ALWAYS_COMB); } -"always_ff" { SV_KEYWORD(TOK_ALWAYS_FF); } -"always_latch" { SV_KEYWORD(TOK_ALWAYS_LATCH); } +"always_comb" { SV_KEYWORD(parser::make_TOK_ALWAYS_COMB(out_loc)); } +"always_ff" { SV_KEYWORD(parser::make_TOK_ALWAYS_FF(out_loc)); } +"always_latch" { SV_KEYWORD(parser::make_TOK_ALWAYS_LATCH(out_loc)); } /* use special token for labels on assert, assume, cover, and restrict because it's insanley complex to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some global state.. its a mess) */ [a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] { - if (!strcmp(yytext, "default")) - return TOK_DEFAULT; - yylval->string = new std::string(std::string("\\") + yytext); - return TOK_SVA_LABEL; + if (!strcmp(YYText(), "default")) + return parser::make_TOK_DEFAULT(out_loc); + string_t val = new std::string(std::string("\\") + YYText()); + return parser::make_TOK_SVA_LABEL(val, out_loc); } -"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } -"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } -"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } -"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } -"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } -"rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } -"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } -"checker" { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); } -"endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); } -"bind" { if (formal_mode) return TOK_BIND; SV_KEYWORD(TOK_BIND); } -"final" { SV_KEYWORD(TOK_FINAL); } -"logic" { SV_KEYWORD(TOK_LOGIC); } -"var" { SV_KEYWORD(TOK_VAR); } -"bit" { SV_KEYWORD(TOK_LOGIC); } -"int" { SV_KEYWORD(TOK_INT); } -"byte" { SV_KEYWORD(TOK_BYTE); } -"shortint" { SV_KEYWORD(TOK_SHORTINT); } -"longint" { SV_KEYWORD(TOK_LONGINT); } -"void" { SV_KEYWORD(TOK_VOID); } +"assert" { if (formal_mode) return parser::make_TOK_ASSERT(out_loc); SV_KEYWORD(parser::make_TOK_ASSERT(out_loc)); } +"assume" { if (formal_mode) return parser::make_TOK_ASSUME(out_loc); SV_KEYWORD(parser::make_TOK_ASSUME(out_loc)); } +"cover" { if (formal_mode) return parser::make_TOK_COVER(out_loc); SV_KEYWORD(parser::make_TOK_COVER(out_loc)); } +"restrict" { if (formal_mode) return parser::make_TOK_RESTRICT(out_loc); SV_KEYWORD(parser::make_TOK_RESTRICT(out_loc)); } +"property" { if (formal_mode) return parser::make_TOK_PROPERTY(out_loc); SV_KEYWORD(parser::make_TOK_PROPERTY(out_loc)); } +"rand" { if (formal_mode) return parser::make_TOK_RAND(out_loc); SV_KEYWORD(parser::make_TOK_RAND(out_loc)); } +"const" { if (formal_mode) return parser::make_TOK_CONST(out_loc); SV_KEYWORD(parser::make_TOK_CONST(out_loc)); } +"checker" { if (formal_mode) return parser::make_TOK_CHECKER(out_loc); SV_KEYWORD(parser::make_TOK_CHECKER(out_loc)); } +"endchecker" { if (formal_mode) return parser::make_TOK_ENDCHECKER(out_loc); SV_KEYWORD(parser::make_TOK_ENDCHECKER(out_loc)); } +"bind" { if (formal_mode) return parser::make_TOK_BIND(out_loc); SV_KEYWORD(parser::make_TOK_BIND(out_loc)); } +"final" { SV_KEYWORD(parser::make_TOK_FINAL(out_loc)); } +"logic" { SV_KEYWORD(parser::make_TOK_LOGIC(out_loc)); } +"var" { SV_KEYWORD(parser::make_TOK_VAR(out_loc)); } +"bit" { SV_KEYWORD(parser::make_TOK_LOGIC(out_loc)); } +"int" { SV_KEYWORD(parser::make_TOK_INT(out_loc)); } +"byte" { SV_KEYWORD(parser::make_TOK_BYTE(out_loc)); } +"shortint" { SV_KEYWORD(parser::make_TOK_SHORTINT(out_loc)); } +"longint" { SV_KEYWORD(parser::make_TOK_LONGINT(out_loc)); } +"void" { SV_KEYWORD(parser::make_TOK_VOID(out_loc)); } -"eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); } -"s_eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); } +"eventually" { if (formal_mode) return parser::make_TOK_EVENTUALLY(out_loc); SV_KEYWORD(parser::make_TOK_EVENTUALLY(out_loc)); } +"s_eventually" { if (formal_mode) return parser::make_TOK_EVENTUALLY(out_loc); SV_KEYWORD(parser::make_TOK_EVENTUALLY(out_loc)); } -"input" { return TOK_INPUT; } -"output" { return TOK_OUTPUT; } -"inout" { return TOK_INOUT; } -"wire" { return TOK_WIRE; } -"tri" { return TOK_WIRE; } -"wor" { return TOK_WOR; } -"trior" { return TOK_WOR; } -"wand" { return TOK_WAND; } -"triand" { return TOK_WAND; } -"reg" { return TOK_REG; } -"integer" { return TOK_INTEGER; } -"signed" { return TOK_SIGNED; } -"unsigned" { SV_KEYWORD(TOK_UNSIGNED); } -"genvar" { return TOK_GENVAR; } -"real" { return TOK_REAL; } +"input" { return parser::make_TOK_INPUT(out_loc); } +"output" { return parser::make_TOK_OUTPUT(out_loc); } +"inout" { return parser::make_TOK_INOUT(out_loc); } +"wire" { return parser::make_TOK_WIRE(out_loc); } +"tri" { return parser::make_TOK_WIRE(out_loc); } +"wor" { return parser::make_TOK_WOR(out_loc); } +"trior" { return parser::make_TOK_WOR(out_loc); } +"wand" { return parser::make_TOK_WAND(out_loc); } +"triand" { return parser::make_TOK_WAND(out_loc); } +"reg" { return parser::make_TOK_REG(out_loc); } +"integer" { return parser::make_TOK_INTEGER(out_loc); } +"signed" { return parser::make_TOK_SIGNED(out_loc); } +"unsigned" { SV_KEYWORD(parser::make_TOK_UNSIGNED(out_loc)); } +"genvar" { return parser::make_TOK_GENVAR(out_loc); } +"real" { return parser::make_TOK_REAL(out_loc); } -"enum" { SV_KEYWORD(TOK_ENUM); } -"typedef" { SV_KEYWORD(TOK_TYPEDEF); } -"struct" { SV_KEYWORD(TOK_STRUCT); } -"union" { SV_KEYWORD(TOK_UNION); } -"packed" { SV_KEYWORD(TOK_PACKED); } +"enum" { SV_KEYWORD(parser::make_TOK_ENUM(out_loc)); } +"typedef" { SV_KEYWORD(parser::make_TOK_TYPEDEF(out_loc)); } +"struct" { SV_KEYWORD(parser::make_TOK_STRUCT(out_loc)); } +"union" { SV_KEYWORD(parser::make_TOK_UNION(out_loc)); } +"packed" { SV_KEYWORD(parser::make_TOK_PACKED(out_loc)); } {UNSIGNED_NUMBER} { - yylval->string = new std::string(yytext); - return TOK_CONSTVAL; + string_t val = new std::string(YYText()); + return parser::make_TOK_CONSTVAL(val, out_loc); } \'[01zxZX] { - yylval->string = new std::string(yytext); - return TOK_UNBASED_UNSIZED_CONSTVAL; + string_t val = new std::string(YYText()); + return parser::make_TOK_UNBASED_UNSIZED_CONSTVAL(val, out_loc); } \'[sS]?[bodhBODH] { BEGIN(BASED_CONST); - yylval->string = new std::string(yytext); - return TOK_BASE; + string_t val = new std::string(YYText()); + return parser::make_TOK_BASE(val, out_loc); } [0-9a-fA-FzxZX?][0-9a-fA-FzxZX?_]* { BEGIN(0); - yylval->string = new std::string(yytext); - return TOK_BASED_CONSTVAL; + string_t val = new std::string(YYText()); + return parser::make_TOK_BASED_CONSTVAL(val, out_loc); } {FIXED_POINT_NUMBER_DEC} { - yylval->string = new std::string(yytext); - return TOK_REALVAL; + string_t val = new std::string(YYText()); + return parser::make_TOK_REALVAL(val, out_loc); } {FIXED_POINT_NUMBER_NO_DEC} { - yylval->string = new std::string(yytext); - return TOK_REALVAL; + string_t val = new std::string(YYText()); + return parser::make_TOK_REALVAL(val, out_loc); } \" { BEGIN(STRING); } -\\. { yymore(); real_location = old_location; } +\\. { yymore(); real_loc = old_loc; } \" { BEGIN(0); - char *yystr = strdup(yytext); - yystr[strlen(yytext) - 1] = 0; + char *yystr = strdup(YYText()); + yystr[strlen(YYText()) - 1] = 0; int i = 0, j = 0; while (yystr[i]) { if (yystr[i] == '\\' && yystr[i + 1]) { @@ -372,72 +410,72 @@ TIME_SCALE_SUFFIX [munpf]?s yystr[j++] = yystr[i++]; } yystr[j] = 0; - yylval->string = new std::string(yystr, j); + string_t val = new std::string(yystr, j); free(yystr); - return TOK_STRING; + return parser::make_TOK_STRING(val, out_loc); } -. { yymore(); real_location = old_location; } +. { yymore(); real_loc = old_loc; } and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 { - yylval->string = new std::string(yytext); - return TOK_PRIMITIVE; + auto val = new std::string(YYText()); + return parser::make_TOK_PRIMITIVE(val, out_loc); } -supply0 { return TOK_SUPPLY0; } -supply1 { return TOK_SUPPLY1; } +supply0 { return parser::make_TOK_SUPPLY0(out_loc); } +supply1 { return parser::make_TOK_SUPPLY1(out_loc); } "$"(display[bho]?|write[bho]?|strobe|monitor|time|realtime|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) { - yylval->string = new std::string(yytext); - return TOK_ID; + auto val = new std::string(YYText()); + return parser::make_TOK_ID(val, out_loc); } "$"(setup|hold|setuphold|removal|recovery|recrem|skew|timeskew|fullskew|nochange) { if (!specify_mode) REJECT; - yylval->string = new std::string(yytext); - return TOK_ID; + auto val = new std::string(YYText()); + return parser::make_TOK_ID(val, out_loc); } "$"(info|warning|error|fatal) { - yylval->string = new std::string(yytext); - return TOK_MSG_TASKS; + auto val = new std::string(YYText()); + return parser::make_TOK_MSG_TASKS(val, out_loc); } -"$signed" { return TOK_TO_SIGNED; } -"$unsigned" { return TOK_TO_UNSIGNED; } +"$signed" { return parser::make_TOK_TO_SIGNED(out_loc); } +"$unsigned" { return parser::make_TOK_TO_UNSIGNED(out_loc); } [a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_$][a-zA-Z0-9_$]* { // package qualifier - auto s = std::string("\\") + yytext; + auto s = std::string("\\") + YYText(); if (pkg_user_types.count(s) > 0) { // package qualified typedefed name - yylval->string = new std::string(s); - return TOK_PKG_USER_TYPE; + auto val = new std::string(s); + return parser::make_TOK_PKG_USER_TYPE(val, out_loc); } else { // backup before :: just return first part - size_t len = strchr(yytext, ':') - yytext; + size_t len = strchr(YYText(), ':') - YYText(); yyless(len); - yylval->string = new std::string(std::string("\\") + yytext); - return TOK_ID; + auto val = new std::string(std::string("\\") + YYText()); + return parser::make_TOK_ID(val, out_loc); } } [a-zA-Z_$][a-zA-Z0-9_$]* { - auto s = std::string("\\") + yytext; + auto s = std::string("\\") + YYText(); if (isUserType(s)) { // previously typedefed name - yylval->string = new std::string(s); - return TOK_USER_TYPE; + auto val = new std::string(s); + return parser::make_TOK_USER_TYPE(val, out_loc); } else { - yylval->string = new std::string(std::string("\\") + yytext); - return TOK_ID; + auto val = new std::string(std::string("\\") + YYText()); + return parser::make_TOK_ID(val, out_loc); } } [a-zA-Z_$][a-zA-Z0-9_$\.]* { - yylval->string = new std::string(std::string("\\") + yytext); - return TOK_ID; + auto val = new std::string(std::string("\\") + YYText()); + return parser::make_TOK_ID(val, out_loc); } "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { @@ -473,7 +511,7 @@ supply1 { return TOK_SUPPLY1; } ); printed_warning = true; } - return TOK_SYNOPSYS_FULL_CASE; + return parser::make_TOK_SYNOPSYS_FULL_CASE(out_loc); } parallel_case { static bool printed_warning = false; @@ -487,119 +525,115 @@ supply1 { return TOK_SUPPLY1; } ); printed_warning = true; } - return TOK_SYNOPSYS_PARALLEL_CASE; + return parser::make_TOK_SYNOPSYS_PARALLEL_CASE(out_loc); } . /* ignore everything else */ "*/" { BEGIN(0); } import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { BEGIN(IMPORT_DPI); - return TOK_DPI_FUNCTION; + return parser::make_TOK_DPI_FUNCTION(out_loc); } [a-zA-Z_$][a-zA-Z0-9_$]* { - yylval->string = new std::string(std::string("\\") + yytext); - return TOK_ID; + auto val = new std::string(std::string("\\") + YYText()); + return parser::make_TOK_ID(val, out_loc); } [ \t\r\n] /* ignore whitespaces */ ";" { BEGIN(0); - return *yytext; + return char_tok(*YYText(), out_loc); } . { - return *yytext; + return char_tok(*YYText(), out_loc); } "\\"[^ \t\r\n]+ { - yylval->string = new std::string(yytext); - return TOK_ID; + auto val = new std::string(YYText()); + return parser::make_TOK_ID(val, out_loc); } -"(*" { return ATTR_BEGIN; } -"*)" { return ATTR_END; } +"(*" { return parser::make_ATTR_BEGIN(out_loc); } +"*)" { return parser::make_ATTR_END(out_loc); } -"{*" { return DEFATTR_BEGIN; } -"*}" { return DEFATTR_END; } +"{*" { return parser::make_DEFATTR_BEGIN(out_loc); } +"*}" { return parser::make_DEFATTR_END(out_loc); } -"**" { return OP_POW; } -"||" { return OP_LOR; } -"&&" { return OP_LAND; } -"==" { return OP_EQ; } -"!=" { return OP_NE; } -"<=" { return OP_LE; } -">=" { return OP_GE; } +"**" { return parser::make_OP_POW(out_loc); } +"||" { return parser::make_OP_LOR(out_loc); } +"&&" { return parser::make_OP_LAND(out_loc); } +"==" { return parser::make_OP_EQ(out_loc); } +"!=" { return parser::make_OP_NE(out_loc); } +"<=" { return parser::make_OP_LE(out_loc); } +">=" { return parser::make_OP_GE(out_loc); } -"===" { return OP_EQX; } -"!==" { return OP_NEX; } +"===" { return parser::make_OP_EQX(out_loc); } +"!==" { return parser::make_OP_NEX(out_loc); } -"~&" { return OP_NAND; } -"~|" { return OP_NOR; } -"~^" { return OP_XNOR; } -"^~" { return OP_XNOR; } +"~&" { return parser::make_OP_NAND(out_loc); } +"~|" { return parser::make_OP_NOR(out_loc); } +"~^" { return parser::make_OP_XNOR(out_loc); } +"^~" { return parser::make_OP_XNOR(out_loc); } -"<<" { return OP_SHL; } -">>" { return OP_SHR; } -"<<<" { return OP_SSHL; } -">>>" { return OP_SSHR; } +"<<" { return parser::make_OP_SHL(out_loc); } +">>" { return parser::make_OP_SHR(out_loc); } +"<<<" { return parser::make_OP_SSHL(out_loc); } +">>>" { return parser::make_OP_SSHR(out_loc); } -"'" { return OP_CAST; } +"'" { return parser::make_OP_CAST(out_loc); } -"::" { return TOK_PACKAGESEP; } -"++" { return TOK_INCREMENT; } -"--" { return TOK_DECREMENT; } +"::" { return parser::make_TOK_PACKAGESEP(out_loc); } +"++" { return parser::make_TOK_INCREMENT(out_loc); } +"--" { return parser::make_TOK_DECREMENT(out_loc); } -"+:" { return TOK_POS_INDEXED; } -"-:" { return TOK_NEG_INDEXED; } +"+:" { return parser::make_TOK_POS_INDEXED(out_loc); } +"-:" { return parser::make_TOK_NEG_INDEXED(out_loc); } -".*" { return TOK_WILDCARD_CONNECT; } +".*" { return parser::make_TOK_WILDCARD_CONNECT(out_loc); } -"|=" { SV_KEYWORD(TOK_BIT_OR_ASSIGN); } -"&=" { SV_KEYWORD(TOK_BIT_AND_ASSIGN); } -"+=" { SV_KEYWORD(TOK_ADD_ASSIGN); } -"-=" { SV_KEYWORD(TOK_SUB_ASSIGN); } -"^=" { SV_KEYWORD(TOK_BIT_XOR_ASSIGN); } -"/=" { SV_KEYWORD(TOK_DIV_ASSIGN); } -"%=" { SV_KEYWORD(TOK_MOD_ASSIGN); } -"*=" { SV_KEYWORD(TOK_MUL_ASSIGN); } -"<<=" { SV_KEYWORD(TOK_SHL_ASSIGN); } -">>=" { SV_KEYWORD(TOK_SHR_ASSIGN); } -"<<<=" { SV_KEYWORD(TOK_SSHL_ASSIGN); } -">>>=" { SV_KEYWORD(TOK_SSHR_ASSIGN); } +"|=" { SV_KEYWORD(parser::make_TOK_BIT_OR_ASSIGN(out_loc)); } +"&=" { SV_KEYWORD(parser::make_TOK_BIT_AND_ASSIGN(out_loc)); } +"+=" { SV_KEYWORD(parser::make_TOK_ADD_ASSIGN(out_loc)); } +"-=" { SV_KEYWORD(parser::make_TOK_SUB_ASSIGN(out_loc)); } +"^=" { SV_KEYWORD(parser::make_TOK_BIT_XOR_ASSIGN(out_loc)); } +"/=" { SV_KEYWORD(parser::make_TOK_DIV_ASSIGN(out_loc)); } +"%=" { SV_KEYWORD(parser::make_TOK_MOD_ASSIGN(out_loc)); } +"*=" { SV_KEYWORD(parser::make_TOK_MUL_ASSIGN(out_loc)); } +"<<=" { SV_KEYWORD(parser::make_TOK_SHL_ASSIGN(out_loc)); } +">>=" { SV_KEYWORD(parser::make_TOK_SHR_ASSIGN(out_loc)); } +"<<<=" { SV_KEYWORD(parser::make_TOK_SSHL_ASSIGN(out_loc)); } +">>>=" { SV_KEYWORD(parser::make_TOK_SSHR_ASSIGN(out_loc)); } [-+]?[=*]> { if (!specify_mode) REJECT; - yylval->string = new std::string(yytext); - return TOK_SPECIFY_OPER; + auto val = new std::string(YYText()); + return parser::make_TOK_SPECIFY_OPER(val, out_loc); } "&&&" { - if (!specify_mode) return TOK_IGNORED_SPECIFY_AND; - return TOK_SPECIFY_AND; + if (!specify_mode) return parser::make_TOK_IGNORED_SPECIFY_AND(out_loc); + return parser::make_TOK_SPECIFY_AND(out_loc); } -{UNSIGNED_NUMBER}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; } -{FIXED_POINT_NUMBER_DEC}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; } -{FIXED_POINT_NUMBER_NO_DEC}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; } +{UNSIGNED_NUMBER}{TIME_SCALE_SUFFIX} { return parser::make_TOK_TIME_SCALE(out_loc); } +{FIXED_POINT_NUMBER_DEC}{TIME_SCALE_SUFFIX} { return parser::make_TOK_TIME_SCALE(out_loc); } +{FIXED_POINT_NUMBER_NO_DEC}{TIME_SCALE_SUFFIX} { return parser::make_TOK_TIME_SCALE(out_loc); } "/*" { comment_caller=YY_START; BEGIN(COMMENT); } . /* ignore comment body */ \n /* ignore comment body */ "*/" { BEGIN(comment_caller); } + [ \t\r\n] /* ignore whitespaces */ \\[\r\n] /* ignore continuation sequence */ "//"[^\r\n]* /* ignore one-line comments */ -. { return *yytext; } -<*>. { BEGIN(0); return *yytext; } +. { return char_tok(*YYText(), out_loc); } +<*>. { BEGIN(0); return char_tok(*YYText(), out_loc); } %% -// this is a hack to avoid the 'yyinput defined but not used' error msgs -void *frontend_verilog_avoid_input_warnings() { - return (void*)&yyinput; -} - diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 9d0956c8e..3e892e9a1 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -34,18 +34,30 @@ */ %require "3.0" +%language "c++" +%define api.value.type variant +%define api.prefix {frontend_verilog_yy} +%define api.token.constructor + +%param { YOSYS_NAMESPACE_PREFIX VERILOG_FRONTEND::VerilogLexer* lexer } + +%code { + // Tell Bison to use lexer.nextToken() for getting tokens + #undef yylex + #define yylex(dummy) lexer->nextToken() +} %{ #include #include +#include #include #include "frontends/verilog/verilog_frontend.h" -#include "frontends/verilog/verilog_parser.tab.hh" #include "kernel/log.h" -#define YYLEX_PARAM &yylval, &yylloc - -USING_YOSYS_NAMESPACE +typedef frontend_verilog_yy::parser::semantic_type YYSTYPE; +typedef frontend_verilog_yy::location YYLTYPE; +USING_YOSYS_NAMESPACE; using namespace AST; using namespace VERILOG_FRONTEND; @@ -53,13 +65,15 @@ YOSYS_NAMESPACE_BEGIN namespace VERILOG_FRONTEND { int port_counter; dict port_stubs; - dict *attr_list, default_attr_list; - std::stack *> attr_list_stack; - dict *albuf; + dict> *attr_list, default_attr_list; + std::stack> *> attr_list_stack; + dict> *albuf; std::vector user_type_stack; dict pkg_user_types; std::vector ast_stack; - struct AstNode *astbuf1, *astbuf2, *astbuf3; + std::unique_ptr astbuf1, astbuf2, astbuf3; + AstNode* cell_hack; + AstNode* member_hack; struct AstNode *current_function_or_task; struct AstNode *current_ast, *current_ast_mod; int current_function_or_task_port_id; @@ -72,76 +86,70 @@ namespace VERILOG_FRONTEND { bool current_wire_rand, current_wire_const; bool current_modport_input, current_modport_output; std::istream *lexin; -} +}; YOSYS_NAMESPACE_END #define SET_AST_NODE_LOC(WHICH, BEGIN, END) \ - do { (WHICH)->location.first_line = (BEGIN).first_line; \ - (WHICH)->location.first_column = (BEGIN).first_column; \ - (WHICH)->location.last_line = (END).last_line; \ - (WHICH)->location.last_column = (END).last_column; } while(0) + do { (WHICH)->location.first_line = (BEGIN).begin.line; \ + (WHICH)->location.first_column = (BEGIN).begin.column; \ + (WHICH)->location.last_line = (END).end.line; \ + (WHICH)->location.last_column = (END).end.column; } while(0) #define SET_RULE_LOC(LHS, BEGIN, END) \ - do { (LHS).first_line = (BEGIN).first_line; \ - (LHS).first_column = (BEGIN).first_column; \ - (LHS).last_line = (END).last_line; \ - (LHS).last_column = (END).last_column; } while(0) + do { (LHS).begin = BEGIN.begin; \ + (LHS).end = (END).end; } while(0) -int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param); +void frontend_verilog_yy::parser::error(const frontend_verilog_yy::parser::location_type& loc, const std::string& msg) +{ + (void) loc; + frontend_verilog_yyerror("%s", msg.c_str()); +} -static void append_attr(AstNode *ast, dict *al) +static void append_attr(AstNode *ast, dict> *al) { for (auto &it : *al) { - if (ast->attributes.count(it.first) > 0) - delete ast->attributes[it.first]; - ast->attributes[it.first] = it.second; + ast->attributes[it.first] = std::move(it.second); } delete al; } -static void append_attr_clone(AstNode *ast, dict *al) +static void append_attr_clone(AstNode *ast, dict> *al) { for (auto &it : *al) { - if (ast->attributes.count(it.first) > 0) - delete ast->attributes[it.first]; ast->attributes[it.first] = it.second->clone(); } } -static void free_attr(dict *al) +static void free_attr(dict> *al) { - for (auto &it : *al) - delete it.second; delete al; } -struct specify_target { - char polarity_op; - AstNode *dst, *dat; -}; +static AstNode* saveChild(std::unique_ptr child) { + auto* child_leaky = child.get(); + ast_stack.back()->children.push_back(std::move(child)); + return child_leaky; +} +static AstNode* pushChild(std::unique_ptr child) { + auto* child_leaky = saveChild(std::move(child)); + ast_stack.push_back(child_leaky); + return child_leaky; +} -struct specify_triple { - AstNode *t_min, *t_avg, *t_max; -}; - -struct specify_rise_fall { - specify_triple rise; - specify_triple fall; -}; - -static void addWiretypeNode(std::string *name, AstNode *node) +static void addWiretypeNode(std::string *name, AstNode* node) { log_assert(node); node->is_custom_type = true; - node->children.push_back(new AstNode(AST_WIRETYPE)); + node->children.push_back(std::make_unique(AST_WIRETYPE)); node->children.back()->str = *name; delete name; } -static void addTypedefNode(std::string *name, AstNode *node) +static void addTypedefNode(std::string *name, std::unique_ptr node) { - log_assert(node); - auto *tnode = new AstNode(AST_TYPEDEF, node); + log_assert((bool)node); + AstNode* tnode = saveChild(std::make_unique(AST_TYPEDEF, std::move(node))); + log_assert((bool)name); tnode->str = *name; auto &user_types = user_type_stack.back(); user_types[*name] = tnode; @@ -151,7 +159,6 @@ static void addTypedefNode(std::string *name, AstNode *node) pkg_user_types[qname] = tnode; } delete name; - ast_stack.back()->children.push_back(tnode); } static void enterTypeScope() @@ -171,9 +178,9 @@ static bool isInLocalScope(const std::string *name) return (user_types.count(*name) > 0); } -static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true) +static std::unique_ptr makeRange(int msb = 31, int lsb = 0, bool isSigned = true) { - auto range = new AstNode(AST_RANGE); + auto range = std::make_unique(AST_RANGE); range->children.push_back(AstNode::mkconst_int(msb, true)); range->children.push_back(AstNode::mkconst_int(lsb, true)); range->is_signed = isSigned; @@ -183,10 +190,10 @@ static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true) static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned = true) { auto range = makeRange(msb, lsb, isSigned); - parent->children.push_back(range); + parent->children.push_back(std::move(range)); } -static AstNode *checkRange(AstNode *type_node, AstNode *range_node) +static std::unique_ptr checkRange(AstNode *type_node, std::unique_ptr range_node) { if (type_node->range_left >= 0 && type_node->range_right >= 0) { // type already restricts the range @@ -203,7 +210,7 @@ static AstNode *checkRange(AstNode *type_node, AstNode *range_node) if (range_node->type == AST_RANGE) { valid = range_node->children.size() == 2; } else { // AST_MULTIRANGE - for (auto child : range_node->children) { + for (auto& child : range_node->children) { valid = valid && child->children.size() == 2; } } @@ -218,20 +225,20 @@ static void rewriteRange(AstNode *rangeNode) { if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { // SV array size [n], rewrite as [0:n-1] - rangeNode->children.push_back(new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true))); + rangeNode->children.push_back(std::make_unique(AST_SUB, std::move(rangeNode->children[0]), AstNode::mkconst_int(1, true))); rangeNode->children[0] = AstNode::mkconst_int(0, false); } } -static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) +static void rewriteAsMemoryNode(AstNode *node, std::unique_ptr rangeNode) { node->type = AST_MEMORY; if (rangeNode->type == AST_MULTIRANGE) { - for (auto *itr : rangeNode->children) - rewriteRange(itr); + for (auto& child : rangeNode->children) + rewriteRange(child.get()); } else - rewriteRange(rangeNode); - node->children.push_back(rangeNode); + rewriteRange(rangeNode.get()); + node->children.push_back(std::move(rangeNode)); } static void checkLabelsMatch(const char *element, const std::string *before, const std::string *after) @@ -255,17 +262,18 @@ static void rewriteGenForDeclInit(AstNode *loop) { // check if this generate for loop contains an inline declaration log_assert(loop->type == AST_GENFOR); - AstNode *decl = loop->children[0]; + auto& decl = loop->children[0]; if (decl->type == AST_ASSIGN_EQ) return; + log_assert(decl->type == AST_GENVAR); log_assert(loop->children.size() == 5); // identify each component of the loop - AstNode *init = loop->children[1]; - AstNode *cond = loop->children[2]; - AstNode *incr = loop->children[3]; - AstNode *body = loop->children[4]; + AstNode *init = loop->children[1].get(); + AstNode *cond = loop->children[2].get(); + AstNode *incr = loop->children[3].get(); + AstNode *body = loop->children[4].get(); log_assert(init->type == AST_ASSIGN_EQ); log_assert(incr->type == AST_ASSIGN_EQ); log_assert(body->type == AST_GENBLOCK); @@ -276,31 +284,31 @@ static void rewriteGenForDeclInit(AstNode *loop) // rename and move the genvar declaration to the containing description decl->str = new_str; - loop->children.erase(loop->children.begin()); log_assert(current_ast_mod != nullptr); - current_ast_mod->children.push_back(decl); + current_ast_mod->children.push_back(std::move(decl)); // create a new localparam with old name so that the items in the loop // can simply use the old name and shadow it as necessary - AstNode *indirect = new AstNode(AST_LOCALPARAM); + auto indirect = std::make_unique(AST_LOCALPARAM); indirect->str = old_str; - AstNode *ident = new AstNode(AST_IDENTIFIER); + auto ident = std::make_unique(AST_IDENTIFIER); ident->str = new_str; - indirect->children.push_back(ident); + indirect->children.push_back(std::move(ident)); - body->children.insert(body->children.begin(), indirect); + body->children.insert(body->children.begin(), std::move(indirect)); // only perform the renaming for the initialization, guard, and // incrementation to enable proper shadowing of the synthetic localparam std::function substitute = [&](AstNode *node) { if (node->type == AST_IDENTIFIER && node->str == old_str) node->str = new_str; - for (AstNode *child : node->children) - substitute(child); + for (auto& child : node->children) + substitute(child.get()); }; substitute(init); substitute(cond); substitute(incr); + loop->children.erase(loop->children.begin()); } static void ensureAsgnExprAllowed() @@ -312,87 +320,127 @@ static void ensureAsgnExprAllowed() } // add a pre/post-increment/decrement statement -static const AstNode *addIncOrDecStmt(dict *stmt_attr, AstNode *lhs, - dict *op_attr, AST::AstNodeType op, +static const AstNode *addIncOrDecStmt(dict> *stmt_attr, + std::unique_ptr lhs, + dict> *op_attr, AST::AstNodeType op, YYLTYPE begin, YYLTYPE end) { - AstNode *one = AstNode::mkconst_int(1, true); - AstNode *rhs = new AstNode(op, lhs->clone(), one); + auto one = AstNode::mkconst_int(1, true); + auto rhs = std::make_unique(op, lhs->clone(), std::move(one)); if (op_attr != nullptr) - append_attr(rhs, op_attr); - AstNode *stmt = new AstNode(AST_ASSIGN_EQ, lhs, rhs); + append_attr(rhs.get(), op_attr); + auto stmt_owned = std::make_unique(AST_ASSIGN_EQ, std::move(lhs), std::move(rhs)); + auto* stmt = stmt_owned.get(); + ast_stack.back()->children.push_back(std::move(stmt_owned)); SET_AST_NODE_LOC(stmt, begin, end); if (stmt_attr != nullptr) append_attr(stmt, stmt_attr); - ast_stack.back()->children.push_back(stmt); return stmt; } // create a pre/post-increment/decrement expression, and add the corresponding statement -static AstNode *addIncOrDecExpr(AstNode *lhs, dict *attr, AST::AstNodeType op, YYLTYPE begin, YYLTYPE end, bool undo) +static std::unique_ptr addIncOrDecExpr(std::unique_ptr lhs, dict> *attr, AST::AstNodeType op, YYLTYPE begin, YYLTYPE end, bool undo) { ensureAsgnExprAllowed(); - const AstNode *stmt = addIncOrDecStmt(nullptr, lhs, attr, op, begin, end); + const AstNode *stmt = addIncOrDecStmt(nullptr, std::move(lhs), attr, op, begin, end); log_assert(stmt->type == AST_ASSIGN_EQ); - AstNode *expr = stmt->children[0]->clone(); + auto expr = stmt->children[0]->clone(); if (undo) { - AstNode *minus_one = AstNode::mkconst_int(-1, true, 1); - expr = new AstNode(op, expr, minus_one); + auto minus_one = AstNode::mkconst_int(-1, true, 1); + expr = std::make_unique(op, std::move(expr), std::move(minus_one)); } - SET_AST_NODE_LOC(expr, begin, end); + SET_AST_NODE_LOC(expr.get(), begin, end); return expr; } // add a binary operator assignment statement, e.g., a += b -static const AstNode *addAsgnBinopStmt(dict *attr, AstNode *lhs, AST::AstNodeType op, AstNode *rhs, YYLTYPE begin, YYLTYPE end) +static std::unique_ptr addAsgnBinopStmt(dict> *attr, std::unique_ptr eq_lhs, AST::AstNodeType op, std::unique_ptr rhs, YYLTYPE begin, YYLTYPE end) { - SET_AST_NODE_LOC(rhs, end, end); + SET_AST_NODE_LOC(rhs.get(), end, end); if (op == AST_SHIFT_LEFT || op == AST_SHIFT_RIGHT || op == AST_SHIFT_SLEFT || op == AST_SHIFT_SRIGHT) { - rhs = new AstNode(AST_TO_UNSIGNED, rhs); - SET_AST_NODE_LOC(rhs, end, end); + rhs = std::make_unique(AST_TO_UNSIGNED, std::move(rhs)); + SET_AST_NODE_LOC(rhs.get(), end, end); } - rhs = new AstNode(op, lhs->clone(), rhs); - AstNode *stmt = new AstNode(AST_ASSIGN_EQ, lhs, rhs); - SET_AST_NODE_LOC(rhs, begin, end); + auto binop_lhs = eq_lhs->clone(); + auto eq_rhs_owned = std::make_unique(op, std::move(binop_lhs), std::move(rhs)); + auto* eq_rhs = eq_rhs_owned.get(); + auto ret_lhs = eq_lhs->clone(); + auto stmt_owned = std::make_unique(AST_ASSIGN_EQ, std::move(eq_lhs), std::move(eq_rhs_owned)); + auto* stmt = stmt_owned.get(); + SET_AST_NODE_LOC(eq_rhs, begin, end); SET_AST_NODE_LOC(stmt, begin, end); - ast_stack.back()->children.push_back(stmt); + ast_stack.back()->children.push_back(std::move(stmt_owned)); if (attr != nullptr) append_attr(stmt, attr); - return lhs; + return ret_lhs; } %} -%define api.prefix {frontend_verilog_yy} -%define api.pure - -/* The union is defined in the header, so we need to provide all the - * includes it requires - */ %code requires { #include #include +#include #include "frontends/verilog/verilog_frontend.h" + +struct specify_target { + char polarity_op; + std::unique_ptr dst, dat; + specify_target& operator=(specify_target&& other) noexcept { + if (this != &other) { + dst = std::move(other.dst); + dat = std::move(other.dat); + polarity_op = other.polarity_op; + } + return *this; + } +}; + +struct specify_triple { + std::unique_ptr t_min, t_avg, t_max; + specify_triple& operator=(specify_triple&& other) noexcept { + if (this != &other) { + t_min = std::move(other.t_min); + t_avg = std::move(other.t_avg); + t_max = std::move(other.t_max); + } + return *this; + } +}; + +struct specify_rise_fall { + specify_triple rise; + specify_triple fall; +}; + +using string_t = std::string *; +using ast_t = std::unique_ptr; +using al_t = YOSYS_NAMESPACE_PREFIX dict>*; +using specify_target_ptr_t = std::unique_ptr; +using specify_triple_ptr_t = std::unique_ptr; +using specify_rise_fall_ptr_t = std::unique_ptr; +using boolean_t = bool; +using ch_t = char; +using integer_t = int; +using ast_node_type_t = YOSYS_NAMESPACE_PREFIX AST::AstNodeType; } -%union { - std::string *string; - struct YOSYS_NAMESPACE_PREFIX AST::AstNode *ast; - YOSYS_NAMESPACE_PREFIX dict *al; - struct specify_target *specify_target_ptr; - struct specify_triple *specify_triple_ptr; - struct specify_rise_fall *specify_rise_fall_ptr; - bool boolean; - char ch; - int integer; - YOSYS_NAMESPACE_PREFIX AST::AstNodeType ast_node_type; -} +%token string_t +%token ast_t +%token al_t +%token specify_target_ptr_t +%token specify_triple_ptr_t +%token specify_rise_fall_ptr_t +%token boolean_t +%token ch_t +%token integer_t +%token ast_node_type_t -%token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE -%token TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS -%token TOK_BASE TOK_BASED_CONSTVAL TOK_UNBASED_UNSIZED_CONSTVAL -%token TOK_USER_TYPE TOK_PKG_USER_TYPE +%token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE +%token TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS +%token TOK_BASE TOK_BASED_CONSTVAL TOK_UNBASED_UNSIZED_CONSTVAL +%token TOK_USER_TYPE TOK_PKG_USER_TYPE %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM @@ -418,36 +466,68 @@ static const AstNode *addAsgnBinopStmt(dict *attr, AstNode * %token TOK_SHL_ASSIGN TOK_SHR_ASSIGN TOK_SSHL_ASSIGN TOK_SSHR_ASSIGN %token TOK_BIND TOK_TIME_SCALE -%type range range_or_multirange non_opt_range non_opt_multirange -%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type -%type opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number -%type type_name -%type opt_enum_init enum_type struct_type enum_struct_type func_return_type typedef_base_type -%type opt_property always_comb_or_latch always_or_always_ff -%type opt_signedness_default_signed opt_signedness_default_unsigned -%type integer_atom_type integer_vector_type -%type attr case_attr -%type struct_union -%type asgn_binop inc_or_dec_op -%type genvar_identifier +%token TOK_EXCL "!" +%token TOK_HASH "#" +%token TOK_PERC "%" +%token TOK_AMP "&" +%token TOK_LPAREN "(" +%token TOK_RPAREN ")" +%token TOK_ASTER "*" +%token TOK_PLUS "+" +%token TOK_COMMA "," +%token TOK_MINUS "-" +%token TOK_DOT "." +%token TOK_SLASH "/" +%token TOK_COL ":" +%token TOK_SEMICOL ";" +%token TOK_LT "<" +%token TOK_EQ "=" +%token TOK_GT ">" +%token TOK_QUE "?" +%token TOK_AT "@" +%token TOK_LBRA "[" +%token TOK_RBRA "]" +%token TOK_CARET "^" +%token TOK_UNDER "_" +%token TOK_LCURL "{" +%token TOK_PIPE "|" +%token TOK_RCURL "}" +%token TOK_TILDE "~" +%token TOK_n "n" +%token TOK_p "p" +%token TOK_x "x" +%token TOK_z "z" -%type specify_target -%type specify_triple specify_opt_triple -%type specify_rise_fall -%type specify_if specify_condition -%type specify_edge +%type range range_or_multirange non_opt_range non_opt_multirange +%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type +%type opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number +%type type_name +%type opt_enum_init enum_type struct_type enum_struct_type func_return_type typedef_base_type +%type opt_property always_comb_or_latch always_or_always_ff +%type opt_signedness_default_signed opt_signedness_default_unsigned +%type integer_atom_type integer_vector_type +%type attr case_attr +%type struct_union +%type asgn_binop inc_or_dec_op +%type genvar_identifier + +%type specify_target +%type specify_triple specify_opt_triple +%type specify_rise_fall +%type specify_if specify_condition +%type specify_edge // operator precedence from low to high %left OP_LOR %left OP_LAND -%left '|' OP_NOR -%left '^' OP_XNOR -%left '&' OP_NAND +%left TOK_PIPE OP_NOR +%left TOK_CARET OP_XNOR +%left TOK_AMP OP_NAND %left OP_EQ OP_NE OP_EQX OP_NEX -%left '<' OP_LE OP_GE '>' +%left TOK_LT OP_LE OP_GE TOK_GT %left OP_SHL OP_SHR OP_SSHL OP_SSHR -%left '+' '-' -%left '*' '/' '%' +%left TOK_PLUS TOK_MINUS +%left TOK_ASTER TOK_SLASH TOK_PERC %left OP_POW %precedence OP_CAST %precedence UNARY_OPS @@ -464,14 +544,12 @@ static const AstNode *addAsgnBinopStmt(dict *attr, AstNode * %% input: { - (void)frontend_verilog_yynerrs; + (void)yynerrs_; ast_stack.clear(); ast_stack.push_back(current_ast); } design { ast_stack.pop_back(); log_assert(GetSize(ast_stack) == 0); - for (auto &it : default_attr_list) - delete it.second; default_attr_list.clear(); }; @@ -491,7 +569,7 @@ attr: { if (attr_list != nullptr) attr_list_stack.push(attr_list); - attr_list = new dict; + attr_list = new dict>; for (auto &it : default_attr_list) (*attr_list)[it.first] = it.second->clone(); } attr_opt { @@ -513,9 +591,7 @@ defattr: DEFATTR_BEGIN { if (attr_list != nullptr) attr_list_stack.push(attr_list); - attr_list = new dict; - for (auto &it : default_attr_list) - delete it.second; + attr_list = new dict>; default_attr_list.clear(); } opt_attr_list { attr_list->swap(default_attr_list); @@ -532,20 +608,14 @@ opt_attr_list: attr_list: attr_assign | - attr_list ',' attr_assign; + attr_list TOK_COMMA attr_assign; attr_assign: hierarchical_id { - if (attr_list->count(*$1) != 0) - delete (*attr_list)[*$1]; (*attr_list)[*$1] = AstNode::mkconst_int(1, false); - delete $1; } | - hierarchical_id '=' expr { - if (attr_list->count(*$1) != 0) - delete (*attr_list)[*$1]; - (*attr_list)[*$1] = $3; - delete $1; + hierarchical_id TOK_EQ expr { + (*attr_list)[*$1] = std::move($3); }; hierarchical_id: @@ -557,22 +627,20 @@ hierarchical_id: *$1 += "::" + $3->substr(1); else *$1 += "::" + *$3; - delete $3; $$ = $1; } | - hierarchical_id '.' TOK_ID { + hierarchical_id TOK_DOT TOK_ID { if ($3->compare(0, 1, "\\") == 0) *$1 += "." + $3->substr(1); else *$1 += "." + *$3; - delete $3; $$ = $1; }; hierarchical_type_id: TOK_USER_TYPE | TOK_PKG_USER_TYPE // package qualified type name - | '(' TOK_USER_TYPE ')' { $$ = $2; } // non-standard grammar + | TOK_LPAREN TOK_USER_TYPE TOK_RPAREN { $$ = $2; } // non-standard grammar ; module: @@ -580,15 +648,13 @@ module: enterTypeScope(); } TOK_ID { do_not_require_port_stubs = false; - AstNode *mod = new AstNode(AST_MODULE); - ast_stack.back()->children.push_back(mod); - ast_stack.push_back(mod); + AstNode* mod = pushChild(std::make_unique(AST_MODULE)); current_ast_mod = mod; port_stubs.clear(); port_counter = 0; mod->str = *$4; append_attr(mod, $1); - } module_para_opt module_args_opt ';' module_body TOK_ENDMODULE opt_label { + } module_para_opt module_args_opt TOK_SEMICOL module_body TOK_ENDMODULE opt_label { if (port_stubs.size() != 0) frontend_verilog_yyerror("Missing details for module port `%s'.", port_stubs.begin()->first.c_str()); @@ -596,58 +662,52 @@ module: ast_stack.pop_back(); log_assert(ast_stack.size() == 1); checkLabelsMatch("Module name", $4, $11); - current_ast_mod = NULL; - delete $4; - delete $11; + current_ast_mod = nullptr; exitTypeScope(); }; module_para_opt: - '#' '(' { astbuf1 = nullptr; } module_para_list { if (astbuf1) delete astbuf1; } ')' | %empty; + TOK_HASH TOK_LPAREN module_para_list TOK_RPAREN | %empty; module_para_list: - single_module_para | module_para_list ',' single_module_para; + single_module_para | module_para_list TOK_COMMA single_module_para; single_module_para: %empty | attr TOK_PARAMETER { - if (astbuf1) delete astbuf1; - astbuf1 = new AstNode(AST_PARAMETER); + astbuf1 = std::make_unique(AST_PARAMETER); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); - append_attr(astbuf1, $1); + append_attr(astbuf1.get(), $1); } param_type single_param_decl | attr TOK_LOCALPARAM { - if (astbuf1) delete astbuf1; - astbuf1 = new AstNode(AST_LOCALPARAM); + astbuf1 = std::make_unique(AST_LOCALPARAM); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); - append_attr(astbuf1, $1); + append_attr(astbuf1.get(), $1); } param_type single_param_decl | single_param_decl; module_args_opt: - '(' ')' | %empty | '(' module_args optional_comma ')'; + TOK_LPAREN TOK_RPAREN | %empty | TOK_LPAREN module_args optional_comma TOK_RPAREN; module_args: - module_arg | module_args ',' module_arg; + module_arg | module_args TOK_COMMA module_arg; optional_comma: - ',' | %empty; + TOK_COMMA | %empty; module_arg_opt_assignment: - '=' expr { + TOK_EQ expr { if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) { if (ast_stack.back()->children.back()->is_input) { - AstNode *n = ast_stack.back()->children.back(); - if (n->attributes.count(ID::defaultvalue)) - delete n->attributes.at(ID::defaultvalue); - n->attributes[ID::defaultvalue] = $2; + auto& n = ast_stack.back()->children.back(); + n->attributes[ID::defaultvalue] = std::move($2); } else { - AstNode *wire = new AstNode(AST_IDENTIFIER); + auto wire = std::make_unique(AST_IDENTIFIER); wire->str = ast_stack.back()->children.back()->str; if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic) - ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2)))); + ast_stack.back()->children.push_back(std::make_unique(AST_INITIAL, std::make_unique(AST_BLOCK, std::make_unique(AST_ASSIGN_LE, std::move(wire), std::move($2))))); else - ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2)); + ast_stack.back()->children.push_back(std::make_unique(AST_ASSIGN, std::move(wire), std::move($2))); } } else frontend_verilog_yyerror("SystemVerilog interface in module port list cannot have a default value."); @@ -657,50 +717,45 @@ module_arg_opt_assignment: module_arg: TOK_ID { if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) { - AstNode *node = ast_stack.back()->children.back()->clone(); + auto node = ast_stack.back()->children.back()->clone(); node->str = *$1; node->port_id = ++port_counter; - ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @1, @1); + SET_AST_NODE_LOC(node.get(), @1, @1); + ast_stack.back()->children.push_back(std::move(node)); } else { if (port_stubs.count(*$1) != 0) frontend_verilog_yyerror("Duplicate module port `%s'.", $1->c_str()); port_stubs[*$1] = ++port_counter; } - delete $1; } module_arg_opt_assignment | TOK_ID { - astbuf1 = new AstNode(AST_INTERFACEPORT); - astbuf1->children.push_back(new AstNode(AST_INTERFACEPORTTYPE)); + astbuf1 = std::make_unique(AST_INTERFACEPORT); + astbuf1->children.push_back(std::make_unique(AST_INTERFACEPORTTYPE)); astbuf1->children[0]->str = *$1; - delete $1; } TOK_ID { /* SV interfaces */ if (!sv_mode) frontend_verilog_yyerror("Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str()); astbuf2 = astbuf1->clone(); // really only needed if multiple instances of same type. astbuf2->str = *$3; - delete $3; astbuf2->port_id = ++port_counter; - ast_stack.back()->children.push_back(astbuf2); - delete astbuf1; // really only needed if multiple instances of same type. + ast_stack.back()->children.push_back(std::move(astbuf2)); } module_arg_opt_assignment | attr wire_type range_or_multirange TOK_ID { - AstNode *node = $2; + auto node = std::move($2); node->str = *$4; - SET_AST_NODE_LOC(node, @4, @4); + SET_AST_NODE_LOC(node.get(), @4, @4); node->port_id = ++port_counter; - AstNode *range = checkRange(node, $3); - if (range != NULL) - node->children.push_back(range); + auto range = checkRange(node.get(), std::move($3)); + if (range != nullptr) + node->children.push_back(std::move(range)); if (!node->is_input && !node->is_output) frontend_verilog_yyerror("Module port `%s' is neither input nor output.", $4->c_str()); if (node->is_reg && node->is_input && !node->is_output && !sv_mode) frontend_verilog_yyerror("Input port `%s' is declared as register.", $4->c_str()); - ast_stack.back()->children.push_back(node); - append_attr(node, $1); - delete $4; + append_attr(node.get(), $1); + ast_stack.back()->children.push_back(std::move(node)); } module_arg_opt_assignment | - '.' '.' '.' { + TOK_DOT TOK_DOT TOK_DOT { do_not_require_port_stubs = true; }; @@ -708,18 +763,14 @@ package: attr TOK_PACKAGE { enterTypeScope(); } TOK_ID { - AstNode *mod = new AstNode(AST_PACKAGE); - ast_stack.back()->children.push_back(mod); - ast_stack.push_back(mod); + AstNode* mod = pushChild(std::make_unique(AST_PACKAGE)); current_ast_mod = mod; mod->str = *$4; append_attr(mod, $1); - } ';' package_body TOK_ENDPACKAGE opt_label { + } TOK_SEMICOL package_body TOK_ENDPACKAGE opt_label { ast_stack.pop_back(); checkLabelsMatch("Package name", $4, $9); - current_ast_mod = NULL; - delete $4; - delete $9; + current_ast_mod = nullptr; exitTypeScope(); }; @@ -734,21 +785,18 @@ interface: enterTypeScope(); } TOK_ID { do_not_require_port_stubs = false; - AstNode *intf = new AstNode(AST_INTERFACE); - ast_stack.back()->children.push_back(intf); - ast_stack.push_back(intf); + AstNode* intf = pushChild(std::make_unique(AST_INTERFACE)); current_ast_mod = intf; port_stubs.clear(); port_counter = 0; intf->str = *$3; - delete $3; - } module_para_opt module_args_opt ';' interface_body TOK_ENDINTERFACE { + } module_para_opt module_args_opt TOK_SEMICOL interface_body TOK_ENDINTERFACE { if (port_stubs.size() != 0) frontend_verilog_yyerror("Missing details for module port `%s'.", port_stubs.begin()->first.c_str()); ast_stack.pop_back(); log_assert(ast_stack.size() == 1); - current_ast_mod = NULL; + current_ast_mod = nullptr; exitTypeScope(); }; @@ -761,9 +809,7 @@ interface_body_stmt: bind_directive: TOK_BIND { - AstNode *bnode = new AstNode(AST_BIND); - ast_stack.back()->children.push_back(bnode); - ast_stack.push_back(bnode); + (void)pushChild(std::make_unique(AST_BIND)); } bind_target { // bind_target should have added at least one child @@ -772,15 +818,14 @@ bind_directive: TOK_ID { // The single_cell parser in cell_list_no_array uses astbuf1 as // a sort of template for constructing cells. - astbuf1 = new AstNode(AST_CELL); - astbuf1->children.push_back(new AstNode(AST_CELLTYPE)); + astbuf1 = std::make_unique(AST_CELL); + astbuf1->children.push_back(std::make_unique(AST_CELLTYPE)); astbuf1->children[0]->str = *$5; - delete $5; } - cell_parameter_list_opt cell_list_no_array ';' { + cell_parameter_list_opt cell_list_no_array TOK_SEMICOL { // cell_list should have added at least one more child log_assert(ast_stack.back()->children.size() >= 2); - delete astbuf1; + (void)astbuf1.reset(); ast_stack.pop_back(); }; @@ -790,7 +835,7 @@ bind_directive: // We can't use the BNF from the spec directly because it's ambiguous: // something like "bind foo bar_i (.*)" can either be interpreted with "foo" as // a module or interface identifier (matching bind_target_scope in the spec) or -// by considering foo as a degenerate hierarchical identifier with no '.' +// by considering foo as a degenerate hierarchical identifier with no TOK_DOT // characters, followed by no bit select (which matches bind_target_instance in // the spec). // @@ -802,54 +847,53 @@ bind_target: // An optional list of target instances for a bind statement, introduced by a // colon. opt_bind_target_instance_list: - ':' bind_target_instance_list | + TOK_COL bind_target_instance_list | %empty; bind_target_instance_list: bind_target_instance | - bind_target_instance_list ',' bind_target_instance; + bind_target_instance_list TOK_COMMA bind_target_instance; // A single target instance for a bind statement. The top of ast_stack will be // the bind node where we should add it. bind_target_instance: hierarchical_id { - auto *node = new AstNode(AST_IDENTIFIER); + auto node = std::make_unique(AST_IDENTIFIER); node->str = *$1; - delete $1; - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(std::move(node)); }; mintypmax_expr: - expr { delete $1; } | - expr ':' expr ':' expr { delete $1; delete $3; delete $5; }; + expr { } | + expr TOK_COL expr TOK_COL expr { }; non_opt_delay: - '#' TOK_ID { delete $2; } | - '#' TOK_CONSTVAL { delete $2; } | - '#' TOK_REALVAL { delete $2; } | + TOK_HASH TOK_ID { } | + TOK_HASH TOK_CONSTVAL { } | + TOK_HASH TOK_REALVAL { } | // our `expr` doesn't have time_scale, so we need the parenthesized variant - '#' TOK_TIME_SCALE | - '#' '(' TOK_TIME_SCALE ')' | - '#' '(' mintypmax_expr ')' | - '#' '(' mintypmax_expr ',' mintypmax_expr ')' | - '#' '(' mintypmax_expr ',' mintypmax_expr ',' mintypmax_expr ')'; + TOK_HASH TOK_TIME_SCALE | + TOK_HASH TOK_LPAREN TOK_TIME_SCALE TOK_RPAREN | + TOK_HASH TOK_LPAREN mintypmax_expr TOK_RPAREN | + TOK_HASH TOK_LPAREN mintypmax_expr TOK_COMMA mintypmax_expr TOK_RPAREN | + TOK_HASH TOK_LPAREN mintypmax_expr TOK_COMMA mintypmax_expr TOK_COMMA mintypmax_expr TOK_RPAREN; delay: non_opt_delay | %empty; io_wire_type: - { astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; } + { astbuf3 = std::make_unique(AST_WIRE); current_wire_rand = false; current_wire_const = false; } wire_type_token_io wire_type_const_rand opt_wire_type_token wire_type_signedness - { $$ = astbuf3; SET_RULE_LOC(@$, @2, @$); }; + { $$ = std::move(astbuf3); SET_RULE_LOC(@$, @2, @$); }; non_io_wire_type: - { astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; } + { astbuf3 = std::make_unique(AST_WIRE); current_wire_rand = false; current_wire_const = false; } wire_type_const_rand wire_type_token wire_type_signedness - { $$ = astbuf3; SET_RULE_LOC(@$, @2, @$); }; + { $$ = std::move(astbuf3); SET_RULE_LOC(@$, @2, @$); }; wire_type: - io_wire_type | - non_io_wire_type; + io_wire_type { $$ = std::move($1); } | + non_io_wire_type { $$ = std::move($1); }; wire_type_token_io: TOK_INPUT { @@ -933,7 +977,7 @@ logic_type: astbuf3->is_signed = true; } | hierarchical_type_id { - addWiretypeNode($1, astbuf3); + addWiretypeNode($1, astbuf3.get()); }; integer_atom_type: @@ -944,59 +988,59 @@ integer_atom_type: TOK_BYTE { $$ = 8; } ; integer_vector_type: - TOK_LOGIC { $$ = TOK_LOGIC; } | - TOK_REG { $$ = TOK_REG; } ; + TOK_LOGIC { $$ = token::TOK_LOGIC; } | + TOK_REG { $$ = token::TOK_REG; } ; non_opt_range: - '[' expr ':' expr ']' { - $$ = new AstNode(AST_RANGE); - $$->children.push_back($2); - $$->children.push_back($4); + TOK_LBRA expr TOK_COL expr TOK_RBRA { + $$ = std::make_unique(AST_RANGE); + $$->children.push_back(std::move($2)); + $$->children.push_back(std::move($4)); } | - '[' expr TOK_POS_INDEXED expr ']' { - $$ = new AstNode(AST_RANGE); - AstNode *expr = new AstNode(AST_SELFSZ, $2); - $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), $4), AstNode::mkconst_int(1, true))); - $$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true))); + TOK_LBRA expr TOK_POS_INDEXED expr TOK_RBRA { + $$ = std::make_unique(AST_RANGE); + auto expr = std::make_unique(AST_SELFSZ, std::move($2)); + $$->children.push_back(std::make_unique(AST_SUB, std::make_unique(AST_ADD, expr->clone(), std::move($4)), AstNode::mkconst_int(1, true))); + $$->children.push_back(std::make_unique(AST_ADD, std::move(expr), AstNode::mkconst_int(0, true))); } | - '[' expr TOK_NEG_INDEXED expr ']' { - $$ = new AstNode(AST_RANGE); - AstNode *expr = new AstNode(AST_SELFSZ, $2); - $$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true))); - $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), AstNode::mkconst_int(1, true)), $4)); + TOK_LBRA expr TOK_NEG_INDEXED expr TOK_RBRA { + $$ = std::make_unique(AST_RANGE); + auto expr = std::make_unique(AST_SELFSZ, std::move($2)); + $$->children.push_back(std::make_unique(AST_ADD, expr->clone(), AstNode::mkconst_int(0, true))); + $$->children.push_back(std::make_unique(AST_SUB, std::make_unique(AST_ADD, std::move(expr), AstNode::mkconst_int(1, true)), std::move($4))); } | - '[' expr ']' { - $$ = new AstNode(AST_RANGE); - $$->children.push_back($2); + TOK_LBRA expr TOK_RBRA { + $$ = std::make_unique(AST_RANGE); + $$->children.push_back(std::move($2)); }; non_opt_multirange: non_opt_range non_opt_range { - $$ = new AstNode(AST_MULTIRANGE, $1, $2); + $$ = std::make_unique(AST_MULTIRANGE, std::move($1), std::move($2)); } | non_opt_multirange non_opt_range { - $$ = $1; - $$->children.push_back($2); + $$ = std::move($1); + $$->children.push_back(std::move($2)); }; range: non_opt_range { - $$ = $1; + $$ = std::move($1); } | %empty { - $$ = NULL; + $$ = nullptr; }; range_or_multirange: - range { $$ = $1; } | - non_opt_multirange { $$ = $1; }; + range { $$ = std::move($1); } | + non_opt_multirange { $$ = std::move($1); }; module_body: module_body module_body_stmt | /* the following line makes the generate..endgenrate keywords optional */ module_body gen_stmt | module_body gen_block | - module_body ';' | + module_body TOK_SEMICOL | %empty; module_body_stmt: @@ -1005,60 +1049,42 @@ module_body_stmt: always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block; checker_decl: - TOK_CHECKER TOK_ID ';' { - AstNode *node = new AstNode(AST_GENBLOCK); + TOK_CHECKER TOK_ID TOK_SEMICOL { + AstNode* node = pushChild(std::make_unique(AST_GENBLOCK)); node->str = *$2; - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); } module_body TOK_ENDCHECKER { - delete $2; ast_stack.pop_back(); }; task_func_decl: attr TOK_DPI_FUNCTION TOK_ID TOK_ID { - current_function_or_task = new AstNode(AST_DPI_FUNCTION, AstNode::mkconst_str(*$3), AstNode::mkconst_str(*$4)); + current_function_or_task = saveChild(std::make_unique(AST_DPI_FUNCTION, AstNode::mkconst_str(*$3), AstNode::mkconst_str(*$4))); current_function_or_task->str = *$4; append_attr(current_function_or_task, $1); - ast_stack.back()->children.push_back(current_function_or_task); - delete $3; - delete $4; - } opt_dpi_function_args ';' { - current_function_or_task = NULL; + } opt_dpi_function_args TOK_SEMICOL { + current_function_or_task = nullptr; } | - attr TOK_DPI_FUNCTION TOK_ID '=' TOK_ID TOK_ID { - current_function_or_task = new AstNode(AST_DPI_FUNCTION, AstNode::mkconst_str(*$5), AstNode::mkconst_str(*$3)); + attr TOK_DPI_FUNCTION TOK_ID TOK_EQ TOK_ID TOK_ID { + current_function_or_task = saveChild(std::make_unique(AST_DPI_FUNCTION, AstNode::mkconst_str(*$5), AstNode::mkconst_str(*$3))); current_function_or_task->str = *$6; append_attr(current_function_or_task, $1); - ast_stack.back()->children.push_back(current_function_or_task); - delete $3; - delete $5; - delete $6; - } opt_dpi_function_args ';' { - current_function_or_task = NULL; + } opt_dpi_function_args TOK_SEMICOL { + current_function_or_task = nullptr; } | - attr TOK_DPI_FUNCTION TOK_ID ':' TOK_ID '=' TOK_ID TOK_ID { - current_function_or_task = new AstNode(AST_DPI_FUNCTION, AstNode::mkconst_str(*$7), AstNode::mkconst_str(*$3 + ":" + RTLIL::unescape_id(*$5))); + attr TOK_DPI_FUNCTION TOK_ID TOK_COL TOK_ID TOK_EQ TOK_ID TOK_ID { + current_function_or_task = saveChild(std::make_unique(AST_DPI_FUNCTION, AstNode::mkconst_str(*$7), AstNode::mkconst_str(*$3 + ":" + RTLIL::unescape_id(*$5)))); current_function_or_task->str = *$8; append_attr(current_function_or_task, $1); - ast_stack.back()->children.push_back(current_function_or_task); - delete $3; - delete $5; - delete $7; - delete $8; - } opt_dpi_function_args ';' { - current_function_or_task = NULL; + } opt_dpi_function_args TOK_SEMICOL { + current_function_or_task = nullptr; } | attr TOK_TASK opt_automatic TOK_ID { - current_function_or_task = new AstNode(AST_TASK); + current_function_or_task = pushChild(std::make_unique(AST_TASK)); current_function_or_task->str = *$4; append_attr(current_function_or_task, $1); - ast_stack.back()->children.push_back(current_function_or_task); - ast_stack.push_back(current_function_or_task); current_function_or_task_port_id = 1; - delete $4; - } task_func_args_opt ';' task_func_body TOK_ENDTASK { - current_function_or_task = NULL; + } task_func_args_opt TOK_SEMICOL task_func_body TOK_ENDTASK { + current_function_or_task = nullptr; ast_stack.pop_back(); } | attr TOK_FUNCTION opt_automatic TOK_VOID TOK_ID { @@ -1067,52 +1093,45 @@ task_func_decl: // inlined, but ignores signals read only in tasks. This only matters // for event based simulation, and for synthesis we can treat a void // function like a task. - current_function_or_task = new AstNode(AST_TASK); + current_function_or_task = pushChild(std::make_unique(AST_TASK)); current_function_or_task->str = *$5; append_attr(current_function_or_task, $1); - ast_stack.back()->children.push_back(current_function_or_task); - ast_stack.push_back(current_function_or_task); current_function_or_task_port_id = 1; - delete $5; - } task_func_args_opt ';' task_func_body TOK_ENDFUNCTION { - current_function_or_task = NULL; + } task_func_args_opt TOK_SEMICOL task_func_body TOK_ENDFUNCTION { + current_function_or_task = nullptr; ast_stack.pop_back(); } | attr TOK_FUNCTION opt_automatic func_return_type TOK_ID { - current_function_or_task = new AstNode(AST_FUNCTION); + current_function_or_task = pushChild(std::make_unique(AST_FUNCTION)); current_function_or_task->str = *$5; append_attr(current_function_or_task, $1); - ast_stack.back()->children.push_back(current_function_or_task); - ast_stack.push_back(current_function_or_task); - AstNode *outreg = new AstNode(AST_WIRE); + auto outreg = std::make_unique(AST_WIRE); outreg->str = *$5; outreg->is_signed = false; outreg->is_reg = true; - if ($4 != NULL) { - outreg->children.push_back($4); + if ($4 != nullptr) { outreg->is_signed = $4->is_signed; $4->is_signed = false; outreg->is_custom_type = $4->type == AST_WIRETYPE; + outreg->children.push_back(std::move($4)); } - current_function_or_task->children.push_back(outreg); + current_function_or_task->children.push_back(std::move(outreg)); current_function_or_task_port_id = 1; - delete $5; - } task_func_args_opt ';' task_func_body TOK_ENDFUNCTION { - current_function_or_task = NULL; + } task_func_args_opt TOK_SEMICOL task_func_body TOK_ENDFUNCTION { + current_function_or_task = nullptr; ast_stack.pop_back(); }; func_return_type: hierarchical_type_id { - $$ = new AstNode(AST_WIRETYPE); + $$ = std::make_unique(AST_WIRETYPE); $$->str = *$1; - delete $1; } | opt_type_vec opt_signedness_default_unsigned { $$ = makeRange(0, 0, $2); } | opt_type_vec opt_signedness_default_unsigned non_opt_range { - $$ = $3; + $$ = std::move($3); $$->is_signed = $2; } | integer_atom_type opt_signedness_default_signed { @@ -1139,21 +1158,18 @@ opt_signedness_default_unsigned: dpi_function_arg: TOK_ID TOK_ID { current_function_or_task->children.push_back(AstNode::mkconst_str(*$1)); - delete $1; - delete $2; } | TOK_ID { current_function_or_task->children.push_back(AstNode::mkconst_str(*$1)); - delete $1; }; opt_dpi_function_args: - '(' dpi_function_args ')' | + TOK_LPAREN dpi_function_args TOK_RPAREN | %empty; dpi_function_args: - dpi_function_args ',' dpi_function_arg | - dpi_function_args ',' | + dpi_function_args TOK_COMMA dpi_function_arg | + dpi_function_args TOK_COMMA | dpi_function_arg | %empty; @@ -1162,19 +1178,19 @@ opt_automatic: %empty; task_func_args_opt: - '(' ')' | %empty | '(' { + TOK_LPAREN TOK_RPAREN | %empty | TOK_LPAREN { albuf = nullptr; astbuf1 = nullptr; astbuf2 = nullptr; } task_func_args optional_comma { - delete astbuf1; - if (astbuf2 != NULL) - delete astbuf2; + (void)astbuf1.reset(); + if (astbuf2 != nullptr) + (void)astbuf2.reset(); free_attr(albuf); - } ')'; + } TOK_RPAREN; task_func_args: - task_func_port | task_func_args ',' task_func_port; + task_func_port | task_func_args TOK_COMMA task_func_port; task_func_port: attr wire_type range_or_multirange { @@ -1183,14 +1199,14 @@ task_func_port: if (albuf) { prev_was_input = astbuf1->is_input; prev_was_output = astbuf1->is_output; - delete astbuf1; - if (astbuf2 != NULL) - delete astbuf2; + (void)astbuf1.reset(); + if (astbuf2 != nullptr) + (void)astbuf2.reset(); free_attr(albuf); } albuf = $1; - astbuf1 = $2; - astbuf2 = checkRange(astbuf1, $3); + astbuf1 = std::move($2); + astbuf2 = checkRange(astbuf1.get(), std::move($3)); if (!astbuf1->is_input && !astbuf1->is_output) { if (!sv_mode) frontend_verilog_yyerror("task/function argument direction missing"); @@ -1202,12 +1218,12 @@ task_func_port: if (!astbuf1) { if (!sv_mode) frontend_verilog_yyerror("task/function argument direction missing"); - albuf = new dict; - astbuf1 = new AstNode(AST_WIRE); + albuf = new dict>; + astbuf1 = std::make_unique(AST_WIRE); current_wire_rand = false; current_wire_const = false; astbuf1->is_input = true; - astbuf2 = NULL; + astbuf2 = nullptr; } } wire_name; @@ -1225,23 +1241,24 @@ specify_item_list: %empty; specify_item: - specify_if '(' specify_edge expr TOK_SPECIFY_OPER specify_target ')' '=' specify_rise_fall ';' { - AstNode *en_expr = $1; + specify_if TOK_LPAREN specify_edge expr TOK_SPECIFY_OPER specify_target TOK_RPAREN TOK_EQ specify_rise_fall TOK_SEMICOL { + auto en_expr = std::move($1); char specify_edge = $3; - AstNode *src_expr = $4; + auto src_expr = std::move($4); string *oper = $5; - specify_target *target = $6; - specify_rise_fall *timing = $9; + specify_target_ptr_t target = std::move($6); + specify_rise_fall_ptr_t timing = std::move($9); if (specify_edge != 0 && target->dat == nullptr) frontend_verilog_yyerror("Found specify edge but no data spec.\n"); - AstNode *cell = new AstNode(AST_CELL); - ast_stack.back()->children.push_back(cell); + auto cell_owned = std::make_unique(AST_CELL); + auto cell = cell_owned.get(); + ast_stack.back()->children.push_back(std::move(cell_owned)); cell->str = stringf("$specify$%d", autoidx++); - cell->children.push_back(new AstNode(AST_CELLTYPE)); + cell->children.push_back(std::make_unique(AST_CELLTYPE)); cell->children.back()->str = target->dat ? "$specify3" : "$specify2"; - SET_AST_NODE_LOC(cell, en_expr ? @1 : @2, @10); + SET_AST_NODE_LOC(cell, en_expr.get() ? @1 : @2, @10); char oper_polarity = 0; char oper_type = oper->at(0); @@ -1251,148 +1268,143 @@ specify_item: oper_type = oper->at(1); } - cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(oper_type == '*', false, 1))); + cell->children.push_back(std::make_unique(AST_PARASET, AstNode::mkconst_int(oper_type == '*', false, 1))); cell->children.back()->str = "\\FULL"; - cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(oper_polarity != 0, false, 1))); + cell->children.push_back(std::make_unique(AST_PARASET, AstNode::mkconst_int(oper_polarity != 0, false, 1))); cell->children.back()->str = "\\SRC_DST_PEN"; - cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(oper_polarity == '+', false, 1))); + cell->children.push_back(std::make_unique(AST_PARASET, AstNode::mkconst_int(oper_polarity == '+', false, 1))); cell->children.back()->str = "\\SRC_DST_POL"; - cell->children.push_back(new AstNode(AST_PARASET, timing->rise.t_min)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(timing->rise.t_min))); cell->children.back()->str = "\\T_RISE_MIN"; - cell->children.push_back(new AstNode(AST_PARASET, timing->rise.t_avg)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(timing->rise.t_avg))); cell->children.back()->str = "\\T_RISE_TYP"; - cell->children.push_back(new AstNode(AST_PARASET, timing->rise.t_max)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(timing->rise.t_max))); cell->children.back()->str = "\\T_RISE_MAX"; - cell->children.push_back(new AstNode(AST_PARASET, timing->fall.t_min)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(timing->fall.t_min))); cell->children.back()->str = "\\T_FALL_MIN"; - cell->children.push_back(new AstNode(AST_PARASET, timing->fall.t_avg)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(timing->fall.t_avg))); cell->children.back()->str = "\\T_FALL_TYP"; - cell->children.push_back(new AstNode(AST_PARASET, timing->fall.t_max)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(timing->fall.t_max))); cell->children.back()->str = "\\T_FALL_MAX"; - cell->children.push_back(new AstNode(AST_ARGUMENT, en_expr ? en_expr : AstNode::mkconst_int(1, false, 1))); + cell->children.push_back(std::make_unique(AST_ARGUMENT, en_expr ? std::move(en_expr) : AstNode::mkconst_int(1, false, 1))); cell->children.back()->str = "\\EN"; - cell->children.push_back(new AstNode(AST_ARGUMENT, src_expr)); + cell->children.push_back(std::make_unique(AST_ARGUMENT, std::move(src_expr))); cell->children.back()->str = "\\SRC"; - cell->children.push_back(new AstNode(AST_ARGUMENT, target->dst)); + cell->children.push_back(std::make_unique(AST_ARGUMENT, std::move(target->dst))); cell->children.back()->str = "\\DST"; if (target->dat) { - cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(specify_edge != 0, false, 1))); + cell->children.push_back(std::make_unique(AST_PARASET, AstNode::mkconst_int(specify_edge != 0, false, 1))); cell->children.back()->str = "\\EDGE_EN"; - cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(specify_edge == 'p', false, 1))); + cell->children.push_back(std::make_unique(AST_PARASET, AstNode::mkconst_int(specify_edge == 'p', false, 1))); cell->children.back()->str = "\\EDGE_POL"; - cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(target->polarity_op != 0, false, 1))); + cell->children.push_back(std::make_unique(AST_PARASET, AstNode::mkconst_int(target->polarity_op != 0, false, 1))); cell->children.back()->str = "\\DAT_DST_PEN"; - cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(target->polarity_op == '+', false, 1))); + cell->children.push_back(std::make_unique(AST_PARASET, AstNode::mkconst_int(target->polarity_op == '+', false, 1))); cell->children.back()->str = "\\DAT_DST_POL"; - cell->children.push_back(new AstNode(AST_ARGUMENT, target->dat)); + cell->children.push_back(std::make_unique(AST_ARGUMENT, std::move(target->dat))); cell->children.back()->str = "\\DAT"; } delete oper; - delete target; - delete timing; } | - TOK_ID '(' specify_edge expr specify_condition ',' specify_edge expr specify_condition ',' specify_triple specify_opt_triple ')' ';' { + TOK_ID TOK_LPAREN specify_edge expr specify_condition TOK_COMMA specify_edge expr specify_condition TOK_COMMA specify_triple specify_opt_triple TOK_RPAREN TOK_SEMICOL { if (*$1 != "$setup" && *$1 != "$hold" && *$1 != "$setuphold" && *$1 != "$removal" && *$1 != "$recovery" && *$1 != "$recrem" && *$1 != "$skew" && *$1 != "$timeskew" && *$1 != "$fullskew" && *$1 != "$nochange") frontend_verilog_yyerror("Unsupported specify rule type: %s\n", $1->c_str()); - AstNode *src_pen = AstNode::mkconst_int($3 != 0, false, 1); - AstNode *src_pol = AstNode::mkconst_int($3 == 'p', false, 1); - AstNode *src_expr = $4, *src_en = $5 ? $5 : AstNode::mkconst_int(1, false, 1); + auto src_pen = AstNode::mkconst_int($3 != 0, false, 1); + auto src_pol = AstNode::mkconst_int($3 == 'p', false, 1); + auto src_expr = std::move($4), src_en = $5 ? std::move($5) : AstNode::mkconst_int(1, false, 1); - AstNode *dst_pen = AstNode::mkconst_int($7 != 0, false, 1); - AstNode *dst_pol = AstNode::mkconst_int($7 == 'p', false, 1); - AstNode *dst_expr = $8, *dst_en = $9 ? $9 : AstNode::mkconst_int(1, false, 1); + auto dst_pen = AstNode::mkconst_int($7 != 0, false, 1); + auto dst_pol = AstNode::mkconst_int($7 == 'p', false, 1); + auto dst_expr = std::move($8), dst_en = $9 ? std::move($9) : AstNode::mkconst_int(1, false, 1); - specify_triple *limit = $11; - specify_triple *limit2 = $12; + specify_triple_ptr_t limit = std::move($11); + specify_triple_ptr_t limit2 = std::move($12); - AstNode *cell = new AstNode(AST_CELL); - ast_stack.back()->children.push_back(cell); + auto cell_owned = std::make_unique(AST_CELL); + auto cell = cell_owned.get(); + ast_stack.back()->children.push_back(std::move(cell_owned)); cell->str = stringf("$specify$%d", autoidx++); - cell->children.push_back(new AstNode(AST_CELLTYPE)); + cell->children.push_back(std::make_unique(AST_CELLTYPE)); cell->children.back()->str = "$specrule"; SET_AST_NODE_LOC(cell, @1, @14); - cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_str(*$1))); + cell->children.push_back(std::make_unique(AST_PARASET, AstNode::mkconst_str(*$1))); cell->children.back()->str = "\\TYPE"; - cell->children.push_back(new AstNode(AST_PARASET, limit->t_min)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(limit->t_min))); cell->children.back()->str = "\\T_LIMIT_MIN"; - cell->children.push_back(new AstNode(AST_PARASET, limit->t_avg)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(limit->t_avg))); cell->children.back()->str = "\\T_LIMIT_TYP"; - cell->children.push_back(new AstNode(AST_PARASET, limit->t_max)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(limit->t_max))); cell->children.back()->str = "\\T_LIMIT_MAX"; - cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2->t_min : AstNode::mkconst_int(0, true))); + cell->children.push_back(std::make_unique(AST_PARASET, limit2 ? std::move(limit2->t_min) : AstNode::mkconst_int(0, true))); cell->children.back()->str = "\\T_LIMIT2_MIN"; - cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2->t_avg : AstNode::mkconst_int(0, true))); + cell->children.push_back(std::make_unique(AST_PARASET, limit2 ? std::move(limit2->t_avg) : AstNode::mkconst_int(0, true))); cell->children.back()->str = "\\T_LIMIT2_TYP"; - cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2->t_max : AstNode::mkconst_int(0, true))); + cell->children.push_back(std::make_unique(AST_PARASET, limit2 ? std::move(limit2->t_max) : AstNode::mkconst_int(0, true))); cell->children.back()->str = "\\T_LIMIT2_MAX"; - cell->children.push_back(new AstNode(AST_PARASET, src_pen)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(src_pen))); cell->children.back()->str = "\\SRC_PEN"; - cell->children.push_back(new AstNode(AST_PARASET, src_pol)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(src_pol))); cell->children.back()->str = "\\SRC_POL"; - cell->children.push_back(new AstNode(AST_PARASET, dst_pen)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(dst_pen))); cell->children.back()->str = "\\DST_PEN"; - cell->children.push_back(new AstNode(AST_PARASET, dst_pol)); + cell->children.push_back(std::make_unique(AST_PARASET, std::move(dst_pol))); cell->children.back()->str = "\\DST_POL"; - cell->children.push_back(new AstNode(AST_ARGUMENT, src_en)); + cell->children.push_back(std::make_unique(AST_ARGUMENT, std::move(src_en))); cell->children.back()->str = "\\SRC_EN"; - cell->children.push_back(new AstNode(AST_ARGUMENT, src_expr)); + cell->children.push_back(std::make_unique(AST_ARGUMENT, std::move(src_expr))); cell->children.back()->str = "\\SRC"; - cell->children.push_back(new AstNode(AST_ARGUMENT, dst_en)); + cell->children.push_back(std::make_unique(AST_ARGUMENT, std::move(dst_en))); cell->children.back()->str = "\\DST_EN"; - cell->children.push_back(new AstNode(AST_ARGUMENT, dst_expr)); + cell->children.push_back(std::make_unique(AST_ARGUMENT, std::move(dst_expr))); cell->children.back()->str = "\\DST"; - - delete $1; - delete limit; - delete limit2; }; specify_opt_triple: - ',' specify_triple { - $$ = $2; + TOK_COMMA specify_triple { + $$ = std::move($2); } | %empty { $$ = nullptr; }; specify_if: - TOK_IF '(' expr ')' { - $$ = $3; + TOK_IF TOK_LPAREN expr TOK_RPAREN { + $$ = std::move($3); } | %empty { $$ = nullptr; @@ -1400,7 +1412,7 @@ specify_if: specify_condition: TOK_SPECIFY_AND expr { - $$ = $2; + $$ = std::move($2); } | %empty { $$ = nullptr; @@ -1408,28 +1420,28 @@ specify_condition: specify_target: expr { - $$ = new specify_target; + $$ = std::make_unique(); $$->polarity_op = 0; - $$->dst = $1; + $$->dst = std::move($1); $$->dat = nullptr; } | - '(' expr ':' expr ')'{ - $$ = new specify_target; + TOK_LPAREN expr TOK_COL expr TOK_RPAREN{ + $$ = std::make_unique(); $$->polarity_op = 0; - $$->dst = $2; - $$->dat = $4; + $$->dst = std::move($2); + $$->dat = std::move($4); } | - '(' expr TOK_NEG_INDEXED expr ')'{ - $$ = new specify_target; + TOK_LPAREN expr TOK_NEG_INDEXED expr TOK_RPAREN{ + $$ = std::make_unique(); $$->polarity_op = '-'; - $$->dst = $2; - $$->dat = $4; + $$->dst = std::move($2); + $$->dat = std::move($4); } | - '(' expr TOK_POS_INDEXED expr ')'{ - $$ = new specify_target; + TOK_LPAREN expr TOK_POS_INDEXED expr TOK_RPAREN{ + $$ = std::make_unique(); $$->polarity_op = '+'; - $$->dst = $2; - $$->dat = $4; + $$->dst = std::move($2); + $$->dat = std::move($4); }; specify_edge: @@ -1439,72 +1451,48 @@ specify_edge: specify_rise_fall: specify_triple { - $$ = new specify_rise_fall; - $$->rise = *$1; + $$ = std::make_unique(); $$->fall.t_min = $1->t_min->clone(); $$->fall.t_avg = $1->t_avg->clone(); $$->fall.t_max = $1->t_max->clone(); - delete $1; + $$->rise = std::move(*$1); } | - '(' specify_triple ',' specify_triple ')' { - $$ = new specify_rise_fall; - $$->rise = *$2; - $$->fall = *$4; - delete $2; - delete $4; + TOK_LPAREN specify_triple TOK_COMMA specify_triple TOK_RPAREN { + $$ = std::make_unique(); + $$->rise = std::move(*$2); + $$->fall = std::move(*$4); } | - '(' specify_triple ',' specify_triple ',' specify_triple ')' { - $$ = new specify_rise_fall; - $$->rise = *$2; - $$->fall = *$4; - delete $2; - delete $4; - delete $6; - log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); + TOK_LPAREN specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_RPAREN { + $$ = std::make_unique(); + $$->rise = std::move(*$2); + $$->fall = std::move(*$4); + log_file_warning(current_filename, @$.begin.line, "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); } | - '(' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ')' { - $$ = new specify_rise_fall; - $$->rise = *$2; - $$->fall = *$4; - delete $2; - delete $4; - delete $6; - delete $8; - delete $10; - delete $12; - log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); + TOK_LPAREN specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_RPAREN { + $$ = std::make_unique(); + $$->rise = std::move(*$2); + $$->fall = std::move(*$4); + log_file_warning(current_filename, @$.begin.line, "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); } | - '(' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ')' { - $$ = new specify_rise_fall; - $$->rise = *$2; - $$->fall = *$4; - delete $2; - delete $4; - delete $6; - delete $8; - delete $10; - delete $12; - delete $14; - delete $16; - delete $18; - delete $20; - delete $22; - delete $24; - log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); + TOK_LPAREN specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_COMMA specify_triple TOK_RPAREN { + $$ = std::make_unique(); + $$->rise = std::move(*$2); + $$->fall = std::move(*$4); + log_file_warning(current_filename, @$.begin.line, "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); } specify_triple: expr { - $$ = new specify_triple; - $$->t_min = $1; + $$ = std::make_unique(); $$->t_avg = $1->clone(); $$->t_max = $1->clone(); + $$->t_min = std::move($1); } | - expr ':' expr ':' expr { - $$ = new specify_triple; - $$->t_min = $1; - $$->t_avg = $3; - $$->t_max = $5; + expr TOK_COL expr TOK_COL expr { + $$ = std::make_unique(); + $$->t_min = std::move($1); + $$->t_avg = std::move($3); + $$->t_max = std::move($5); }; /******************** ignored specify parser **************************/ @@ -1526,58 +1514,58 @@ ignored_specify_item: ; specparam_declaration: - TOK_SPECPARAM list_of_specparam_assignments ';' | - TOK_SPECPARAM specparam_range list_of_specparam_assignments ';' ; + TOK_SPECPARAM list_of_specparam_assignments TOK_SEMICOL | + TOK_SPECPARAM specparam_range list_of_specparam_assignments TOK_SEMICOL ; // IEEE 1364-2005 calls this sinmply 'range' but the current 'range' rule allows empty match // and the 'non_opt_range' rule allows index ranges not allowed by 1364-2005 // exxxxtending this for SV specparam would change this anyhow specparam_range: - '[' ignspec_constant_expression ':' ignspec_constant_expression ']' ; + TOK_LBRA ignspec_constant_expression TOK_COL ignspec_constant_expression TOK_RBRA ; list_of_specparam_assignments: - specparam_assignment | list_of_specparam_assignments ',' specparam_assignment; + specparam_assignment | list_of_specparam_assignments TOK_COMMA specparam_assignment; specparam_assignment: - ignspec_id '=' ignspec_expr ; + ignspec_id TOK_EQ ignspec_expr ; ignspec_opt_cond: - TOK_IF '(' ignspec_expr ')' | %empty; + TOK_IF TOK_LPAREN ignspec_expr TOK_RPAREN | %empty; path_declaration : - simple_path_declaration ';' + simple_path_declaration TOK_SEMICOL // | edge_sensitive_path_declaration // | state_dependent_path_declaration ; simple_path_declaration : - ignspec_opt_cond parallel_path_description '=' path_delay_value | - ignspec_opt_cond full_path_description '=' path_delay_value + ignspec_opt_cond parallel_path_description TOK_EQ path_delay_value | + ignspec_opt_cond full_path_description TOK_EQ path_delay_value ; path_delay_value : - '(' ignspec_expr list_of_path_delay_extra_expressions ')' + TOK_LPAREN ignspec_expr list_of_path_delay_extra_expressions TOK_RPAREN | ignspec_expr | ignspec_expr list_of_path_delay_extra_expressions ; list_of_path_delay_extra_expressions : - ',' ignspec_expr - | ',' ignspec_expr list_of_path_delay_extra_expressions + TOK_COMMA ignspec_expr + | TOK_COMMA ignspec_expr list_of_path_delay_extra_expressions ; specify_edge_identifier : TOK_POSEDGE | TOK_NEGEDGE ; parallel_path_description : - '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' | - '(' specify_edge_identifier specify_input_terminal_descriptor '=' '>' '(' specify_output_terminal_descriptor opt_polarity_operator ':' ignspec_expr ')' ')' | - '(' specify_edge_identifier specify_input_terminal_descriptor '=' '>' '(' specify_output_terminal_descriptor TOK_POS_INDEXED ignspec_expr ')' ')' ; + TOK_LPAREN specify_input_terminal_descriptor opt_polarity_operator TOK_EQ TOK_GT specify_output_terminal_descriptor TOK_RPAREN | + TOK_LPAREN specify_edge_identifier specify_input_terminal_descriptor TOK_EQ TOK_GT TOK_LPAREN specify_output_terminal_descriptor opt_polarity_operator TOK_COL ignspec_expr TOK_RPAREN TOK_RPAREN | + TOK_LPAREN specify_edge_identifier specify_input_terminal_descriptor TOK_EQ TOK_GT TOK_LPAREN specify_output_terminal_descriptor TOK_POS_INDEXED ignspec_expr TOK_RPAREN TOK_RPAREN ; full_path_description : - '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' | - '(' specify_edge_identifier list_of_path_inputs '*' '>' '(' list_of_path_outputs opt_polarity_operator ':' ignspec_expr ')' ')' | - '(' specify_edge_identifier list_of_path_inputs '*' '>' '(' list_of_path_outputs TOK_POS_INDEXED ignspec_expr ')' ')' ; + TOK_LPAREN list_of_path_inputs TOK_ASTER TOK_GT list_of_path_outputs TOK_RPAREN | + TOK_LPAREN specify_edge_identifier list_of_path_inputs TOK_ASTER TOK_GT TOK_LPAREN list_of_path_outputs opt_polarity_operator TOK_COL ignspec_expr TOK_RPAREN TOK_RPAREN | + TOK_LPAREN specify_edge_identifier list_of_path_inputs TOK_ASTER TOK_GT TOK_LPAREN list_of_path_outputs TOK_POS_INDEXED ignspec_expr TOK_RPAREN TOK_RPAREN ; // This was broken into 2 rules to solve shift/reduce conflicts list_of_path_inputs : @@ -1585,15 +1573,15 @@ list_of_path_inputs : specify_input_terminal_descriptor more_path_inputs opt_polarity_operator ; more_path_inputs : - ',' specify_input_terminal_descriptor | - more_path_inputs ',' specify_input_terminal_descriptor ; + TOK_COMMA specify_input_terminal_descriptor | + more_path_inputs TOK_COMMA specify_input_terminal_descriptor ; list_of_path_outputs : specify_output_terminal_descriptor | - list_of_path_outputs ',' specify_output_terminal_descriptor ; + list_of_path_outputs TOK_COMMA specify_output_terminal_descriptor ; opt_polarity_operator : - '+' | '-' | %empty; + TOK_PLUS | TOK_MINUS | %empty; // Good enough for the time being specify_input_terminal_descriptor : @@ -1604,7 +1592,7 @@ specify_output_terminal_descriptor : ignspec_id ; system_timing_declaration : - ignspec_id '(' system_timing_args ')' ';' ; + ignspec_id TOK_LPAREN system_timing_args TOK_RPAREN TOK_SEMICOL ; system_timing_arg : TOK_POSEDGE ignspec_id | @@ -1614,26 +1602,23 @@ system_timing_arg : system_timing_args : system_timing_arg | system_timing_args TOK_IGNORED_SPECIFY_AND system_timing_arg | - system_timing_args ',' system_timing_arg ; + system_timing_args TOK_COMMA system_timing_arg ; // for the time being this is OK, but we may write our own expr here. // as I'm not sure it is legal to use a full expr here (probably not) // On the other hand, other rules requiring constant expressions also use 'expr' // (such as param assignment), so we may leave this as-is, perhaps adding runtime checks for constant-ness ignspec_constant_expression: - expr { delete $1; }; + expr { }; ignspec_expr: - expr { delete $1; } | - expr ':' expr ':' expr { - delete $1; - delete $3; - delete $5; + expr { } | + expr TOK_COL expr TOK_COL expr { }; ignspec_id: - TOK_ID { delete $1; } - range_or_multirange { delete $3; }; + TOK_ID { } + range_or_multirange { }; /**********************************************************************/ @@ -1651,103 +1636,101 @@ param_integer: param_real: TOK_REAL { - astbuf1->children.push_back(new AstNode(AST_REALVALUE)); + astbuf1->children.push_back(std::make_unique(AST_REALVALUE)); }; param_range: range { - if ($1 != NULL) { - astbuf1->children.push_back($1); + if ($1 != nullptr) { + astbuf1->children.push_back(std::move($1)); } }; param_integer_type: param_integer param_signed; param_range_type: type_vec param_signed { - addRange(astbuf1, 0, 0); + addRange(astbuf1.get(), 0, 0); } | type_vec param_signed non_opt_range { - astbuf1->children.push_back($3); + astbuf1->children.push_back(std::move($3)); }; param_implicit_type: param_signed param_range; param_type: param_integer_type | param_real | param_range_type | param_implicit_type | hierarchical_type_id { - addWiretypeNode($1, astbuf1); + addWiretypeNode($1, astbuf1.get()); }; param_decl: attr TOK_PARAMETER { - astbuf1 = new AstNode(AST_PARAMETER); + astbuf1 = std::make_unique(AST_PARAMETER); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); - append_attr(astbuf1, $1); - } param_type param_decl_list ';' { - delete astbuf1; + append_attr(astbuf1.get(), $1); + } param_type param_decl_list TOK_SEMICOL { + (void)astbuf1.reset(); }; localparam_decl: attr TOK_LOCALPARAM { - astbuf1 = new AstNode(AST_LOCALPARAM); + astbuf1 = std::make_unique(AST_LOCALPARAM); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); - append_attr(astbuf1, $1); - } param_type param_decl_list ';' { - delete astbuf1; + append_attr(astbuf1.get(), $1); + } param_type param_decl_list TOK_SEMICOL { + (void)astbuf1.reset(); }; param_decl_list: - single_param_decl | param_decl_list ',' single_param_decl; + single_param_decl | param_decl_list TOK_COMMA single_param_decl; single_param_decl: - single_param_decl_ident '=' expr { - AstNode *decl = ast_stack.back()->children.back(); + single_param_decl_ident TOK_EQ expr { + AstNode *decl = ast_stack.back()->children.back().get(); log_assert(decl->type == AST_PARAMETER || decl->type == AST_LOCALPARAM); - delete decl->children[0]; - decl->children[0] = $3; + decl->children[0] = std::move($3); } | single_param_decl_ident { - AstNode *decl = ast_stack.back()->children.back(); + AstNode *decl = ast_stack.back()->children.back().get(); if (decl->type != AST_PARAMETER) { log_assert(decl->type == AST_LOCALPARAM); frontend_verilog_yyerror("localparam initialization is missing!"); } if (!sv_mode) frontend_verilog_yyerror("Parameter defaults can only be omitted in SystemVerilog mode!"); - delete decl->children[0]; decl->children.erase(decl->children.begin()); }; single_param_decl_ident: TOK_ID { - AstNode *node; + std::unique_ptr node_owned; if (astbuf1 == nullptr) { if (!sv_mode) frontend_verilog_yyerror("In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword"); - node = new AstNode(AST_PARAMETER); - node->children.push_back(AstNode::mkconst_int(0, true)); + node_owned = std::make_unique(AST_PARAMETER); + node_owned->children.push_back(AstNode::mkconst_int(0, true)); } else { - node = astbuf1->clone(); + node_owned = astbuf1->clone(); } - node->str = *$1; - ast_stack.back()->children.push_back(node); - delete $1; + node_owned->str = *$1; + auto node = node_owned.get(); + ast_stack.back()->children.push_back(std::move(node_owned)); SET_AST_NODE_LOC(node, @1, @1); }; defparam_decl: - TOK_DEFPARAM defparam_decl_list ';'; + TOK_DEFPARAM defparam_decl_list TOK_SEMICOL; defparam_decl_list: - single_defparam_decl | defparam_decl_list ',' single_defparam_decl; + single_defparam_decl | defparam_decl_list TOK_COMMA single_defparam_decl; single_defparam_decl: - range rvalue '=' expr { - AstNode *node = new AstNode(AST_DEFPARAM); - node->children.push_back($2); - node->children.push_back($4); - if ($1 != NULL) - node->children.push_back($1); - ast_stack.back()->children.push_back(node); + range rvalue TOK_EQ expr { + auto node = std::make_unique(AST_DEFPARAM); + node->children.push_back(std::move($2)); + node->children.push_back(std::move($4)); + if ($1 != nullptr) + node->children.push_back(std::move($1)); + ast_stack.back()->children.push_back(std::move(node)); }; ///////// @@ -1757,36 +1740,39 @@ single_defparam_decl: enum_type: TOK_ENUM { static int enum_count; // create parent node for the enum - astbuf2 = new AstNode(AST_ENUM); - ast_stack.back()->children.push_back(astbuf2); + astbuf2 = std::make_unique(AST_ENUM); astbuf2->str = std::string("$enum"); astbuf2->str += std::to_string(enum_count++); + log_assert(!cell_hack); + cell_hack = astbuf2.get(); + ast_stack.back()->children.push_back(std::move(astbuf2)); // create the template for the names - astbuf1 = new AstNode(AST_ENUM_ITEM); + astbuf1 = std::make_unique(AST_ENUM_ITEM); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); - } enum_base_type '{' enum_name_list optional_comma '}' { + } enum_base_type TOK_LCURL enum_name_list optional_comma TOK_RCURL { // create template for the enum vars - auto tnode = astbuf1->clone(); - delete astbuf1; - astbuf1 = tnode; + log_assert(cell_hack); + auto tnode_owned = astbuf1->clone(); + auto* tnode = tnode_owned.get(); + astbuf1 = std::move(tnode_owned); tnode->type = AST_WIRE; - tnode->attributes[ID::enum_type] = AstNode::mkconst_str(astbuf2->str); + tnode->attributes[ID::enum_type] = AstNode::mkconst_str(cell_hack->str); + cell_hack = nullptr; // drop constant but keep any range - delete tnode->children[0]; tnode->children.erase(tnode->children.begin()); - $$ = astbuf1; + $$ = astbuf1->clone(); }; enum_base_type: type_atom type_signing - | type_vec type_signing range { if ($3) astbuf1->children.push_back($3); } - | %empty { astbuf1->is_reg = true; addRange(astbuf1); } + | type_vec type_signing range { if ($3) astbuf1->children.push_back(std::move($3)); } + | %empty { astbuf1->is_reg = true; addRange(astbuf1.get()); } ; type_atom: integer_atom_type { astbuf1->is_reg = true; astbuf1->is_signed = true; - addRange(astbuf1, $1 - 1, 0); + addRange(astbuf1.get(), $1 - 1, 0); }; type_vec: TOK_REG { astbuf1->is_reg = true; } // unsigned @@ -1800,47 +1786,43 @@ type_signing: ; enum_name_list: enum_name_decl - | enum_name_list ',' enum_name_decl + | enum_name_list TOK_COMMA enum_name_decl ; enum_name_decl: TOK_ID opt_enum_init { // put in fn - log_assert(astbuf1); - log_assert(astbuf2); + log_assert((bool)astbuf1); + log_assert((bool)cell_hack); auto node = astbuf1->clone(); node->str = *$1; - delete $1; - SET_AST_NODE_LOC(node, @1, @1); - delete node->children[0]; - node->children[0] = $2 ? $2 : new AstNode(AST_NONE); - astbuf2->children.push_back(node); + SET_AST_NODE_LOC(node.get(), @1, @1); + node->children[0] = $2 ? std::move($2) : std::make_unique(AST_NONE); + cell_hack->children.push_back(std::move(node)); } ; opt_enum_init: - '=' basic_expr { $$ = $2; } // TODO: restrict this - | %empty { $$ = NULL; } + TOK_EQ basic_expr { $$ = std::move($2); } // TODO: restrict this + | %empty { $$ = nullptr; } ; enum_var_list: enum_var - | enum_var_list ',' enum_var + | enum_var_list TOK_COMMA enum_var ; enum_var: TOK_ID { - log_assert(astbuf1); - log_assert(astbuf2); + log_assert((bool)astbuf1); auto node = astbuf1->clone(); - ast_stack.back()->children.push_back(node); node->str = *$1; - delete $1; - SET_AST_NODE_LOC(node, @1, @1); + SET_AST_NODE_LOC(node.get(), @1, @1); node->is_enum = true; + ast_stack.back()->children.push_back(std::move(node)); } ; -enum_decl: enum_type enum_var_list ';' { delete $1; } +enum_decl: enum_type enum_var_list TOK_SEMICOL { } ; ////////////////// @@ -1849,21 +1831,26 @@ enum_decl: enum_type enum_var_list ';' { delete $1; } struct_decl: attr struct_type { - append_attr($2, $1); - } struct_var_list ';' { - delete astbuf2; + append_attr(astbuf2.get(), $1); + } struct_var_list TOK_SEMICOL { + (void)astbuf2.reset(); } ; -struct_type: struct_union { astbuf2 = $1; } struct_body { $$ = astbuf2; } +struct_type: + struct_union { + astbuf2 = std::move($1); + } struct_body { + $$ = astbuf2->clone(); + } ; struct_union: - TOK_STRUCT { $$ = new AstNode(AST_STRUCT); } - | TOK_UNION { $$ = new AstNode(AST_UNION); } + TOK_STRUCT { $$ = std::make_unique(AST_STRUCT); } + | TOK_UNION { $$ = std::make_unique(AST_UNION); } ; -struct_body: opt_packed '{' struct_member_list '}' +struct_body: opt_packed TOK_LCURL struct_member_list TOK_RCURL ; opt_packed: @@ -1880,62 +1867,68 @@ struct_member_list: struct_member | struct_member_list struct_member ; -struct_member: struct_member_type member_name_list ';' { delete astbuf1; } +struct_member: struct_member_type member_name_list TOK_SEMICOL { (void)astbuf1.reset(); } ; member_name_list: member_name - | member_name_list ',' member_name + | member_name_list TOK_COMMA member_name ; member_name: TOK_ID { - astbuf1->str = $1->substr(1); - delete $1; - astbuf3 = astbuf1->clone(); - SET_AST_NODE_LOC(astbuf3, @1, @1); - astbuf2->children.push_back(astbuf3); - } range { if ($3) astbuf3->children.push_back($3); } + astbuf1->str = $1->substr(1); + astbuf3 = astbuf1->clone(); + log_assert(!member_hack); + member_hack = astbuf3.get(); + SET_AST_NODE_LOC(member_hack, @1, @1); + astbuf2->children.push_back(std::move(astbuf3)); + } range { + log_assert((bool)member_hack); + if ($3) member_hack->children.push_back(std::move($3)); + member_hack = nullptr; + } ; -struct_member_type: { astbuf1 = new AstNode(AST_STRUCT_ITEM); } member_type_token +struct_member_type: { astbuf1 = std::make_unique(AST_STRUCT_ITEM); } member_type_token ; member_type_token: member_type range_or_multirange { - AstNode *range = checkRange(astbuf1, $2); + auto range = checkRange(astbuf1.get(), std::move($2)); if (range) - astbuf1->children.push_back(range); + astbuf1->children.push_back(std::move(range)); } | { - delete astbuf1; + (void)astbuf1.reset(); } struct_union { // stash state on ast_stack - ast_stack.push_back(astbuf2); - astbuf2 = $2; + // sketchy! + ast_stack.push_back(astbuf2.release()); + astbuf2 = std::move($2); } struct_body { - astbuf1 = astbuf2; + astbuf1 = std::move(astbuf2); // recover state - astbuf2 = ast_stack.back(); + astbuf2.reset(ast_stack.back()); ast_stack.pop_back(); } ; member_type: type_atom type_signing | type_vec type_signing - | hierarchical_type_id { addWiretypeNode($1, astbuf1); } + | hierarchical_type_id { addWiretypeNode($1, astbuf1.get()); } ; struct_var_list: struct_var - | struct_var_list ',' struct_var + | struct_var_list TOK_COMMA struct_var ; -struct_var: TOK_ID { auto *var_node = astbuf2->clone(); - var_node->str = *$1; - delete $1; - SET_AST_NODE_LOC(var_node, @1, @1); - ast_stack.back()->children.push_back(var_node); - } - ; +struct_var: + TOK_ID { + auto var_node = astbuf2->clone(); + var_node->str = *$1; + SET_AST_NODE_LOC(var_node.get(), @1, @1); + ast_stack.back()->children.push_back(std::move(var_node)); + }; ///////// // wire @@ -1944,45 +1937,42 @@ struct_var: TOK_ID { auto *var_node = astbuf2->clone(); wire_decl: attr wire_type range_or_multirange { albuf = $1; - astbuf1 = $2; - astbuf2 = checkRange(astbuf1, $3); + astbuf1 = std::move($2); + astbuf2 = checkRange(astbuf1.get(), std::move($3)); } delay wire_name_list { - delete astbuf1; - if (astbuf2 != NULL) - delete astbuf2; + (void)astbuf1.reset(); + if (astbuf2 != nullptr) + (void)astbuf2.reset(); free_attr(albuf); - } ';' | + } TOK_SEMICOL | attr TOK_SUPPLY0 TOK_ID { - ast_stack.back()->children.push_back(new AstNode(AST_WIRE)); + ast_stack.back()->children.push_back(std::make_unique(AST_WIRE)); ast_stack.back()->children.back()->str = *$3; - append_attr(ast_stack.back()->children.back(), $1); - ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(0, false, 1))); + append_attr(ast_stack.back()->children.back().get(), $1); + ast_stack.back()->children.push_back(std::make_unique(AST_ASSIGN, std::make_unique(AST_IDENTIFIER), AstNode::mkconst_int(0, false, 1))); ast_stack.back()->children.back()->children[0]->str = *$3; - delete $3; - } opt_supply_wires ';' | + } opt_supply_wires TOK_SEMICOL | attr TOK_SUPPLY1 TOK_ID { - ast_stack.back()->children.push_back(new AstNode(AST_WIRE)); + ast_stack.back()->children.push_back(std::make_unique(AST_WIRE)); ast_stack.back()->children.back()->str = *$3; - append_attr(ast_stack.back()->children.back(), $1); - ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(1, false, 1))); + append_attr(ast_stack.back()->children.back().get(), $1); + ast_stack.back()->children.push_back(std::make_unique(AST_ASSIGN, std::make_unique(AST_IDENTIFIER), AstNode::mkconst_int(1, false, 1))); ast_stack.back()->children.back()->children[0]->str = *$3; - delete $3; - } opt_supply_wires ';'; + } opt_supply_wires TOK_SEMICOL; opt_supply_wires: %empty | - opt_supply_wires ',' TOK_ID { - AstNode *wire_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-2)->clone(); - AstNode *assign_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-1)->clone(); + opt_supply_wires TOK_COMMA TOK_ID { + auto wire_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-2)->clone(); + auto assign_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-1)->clone(); wire_node->str = *$3; assign_node->children[0]->str = *$3; - ast_stack.back()->children.push_back(wire_node); - ast_stack.back()->children.push_back(assign_node); - delete $3; + ast_stack.back()->children.push_back(std::move(wire_node)); + ast_stack.back()->children.push_back(std::move(assign_node)); }; wire_name_list: - wire_name_and_opt_assign | wire_name_list ',' wire_name_and_opt_assign; + wire_name_and_opt_assign | wire_name_list TOK_COMMA wire_name_and_opt_assign; wire_name_and_opt_assign: wire_name { @@ -1991,28 +1981,24 @@ wire_name_and_opt_assign: bool attr_allconst = false; bool attr_allseq = false; if (ast_stack.back()->children.back()->get_bool_attribute(ID::anyconst)) { - delete ast_stack.back()->children.back()->attributes.at(ID::anyconst); ast_stack.back()->children.back()->attributes.erase(ID::anyconst); attr_anyconst = true; } if (ast_stack.back()->children.back()->get_bool_attribute(ID::anyseq)) { - delete ast_stack.back()->children.back()->attributes.at(ID::anyseq); ast_stack.back()->children.back()->attributes.erase(ID::anyseq); attr_anyseq = true; } if (ast_stack.back()->children.back()->get_bool_attribute(ID::allconst)) { - delete ast_stack.back()->children.back()->attributes.at(ID::allconst); ast_stack.back()->children.back()->attributes.erase(ID::allconst); attr_allconst = true; } if (ast_stack.back()->children.back()->get_bool_attribute(ID::allseq)) { - delete ast_stack.back()->children.back()->attributes.at(ID::allseq); ast_stack.back()->children.back()->attributes.erase(ID::allseq); attr_allseq = true; } if (current_wire_rand || attr_anyconst || attr_anyseq || attr_allconst || attr_allseq) { - AstNode *wire = new AstNode(AST_IDENTIFIER); - AstNode *fcall = new AstNode(AST_FCALL); + auto wire = std::make_unique(AST_IDENTIFIER); + auto fcall = std::make_unique(AST_FCALL); wire->str = ast_stack.back()->children.back()->str; fcall->str = current_wire_const ? "\\$anyconst" : "\\$anyseq"; if (attr_anyconst) @@ -2024,32 +2010,29 @@ wire_name_and_opt_assign: if (attr_allseq) fcall->str = "\\$allseq"; fcall->attributes[ID::reg] = AstNode::mkconst_str(RTLIL::unescape_id(wire->str)); - ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, fcall)); + ast_stack.back()->children.push_back(std::make_unique(AST_ASSIGN, std::move(wire), std::move(fcall))); } } | - wire_name '=' expr { - AstNode *wire = new AstNode(AST_IDENTIFIER); + wire_name TOK_EQ expr { + auto wire = std::make_unique(AST_IDENTIFIER); wire->str = ast_stack.back()->children.back()->str; if (astbuf1->is_input) { - if (astbuf1->attributes.count(ID::defaultvalue)) - delete astbuf1->attributes.at(ID::defaultvalue); - astbuf1->attributes[ID::defaultvalue] = $3; + astbuf1->attributes[ID::defaultvalue] = std::move($3); } else if (astbuf1->is_reg || astbuf1->is_logic){ - AstNode *assign = new AstNode(AST_ASSIGN_LE, wire, $3); - AstNode *block = new AstNode(AST_BLOCK, assign); - AstNode *init = new AstNode(AST_INITIAL, block); + auto assign = std::make_unique(AST_ASSIGN_LE, std::move(wire), std::move($3)); + SET_AST_NODE_LOC(assign.get(), @1, @3); + auto block = std::make_unique(AST_BLOCK, std::move(assign)); + SET_AST_NODE_LOC(block.get(), @1, @3); + auto init = std::make_unique(AST_INITIAL, std::move(block)); + SET_AST_NODE_LOC(init.get(), @1, @3); - SET_AST_NODE_LOC(assign, @1, @3); - SET_AST_NODE_LOC(block, @1, @3); - SET_AST_NODE_LOC(init, @1, @3); - - ast_stack.back()->children.push_back(init); + ast_stack.back()->children.push_back(std::move(init)); } else { - AstNode *assign = new AstNode(AST_ASSIGN, wire, $3); - SET_AST_NODE_LOC(assign, @1, @3); - ast_stack.back()->children.push_back(assign); + auto assign = std::make_unique(AST_ASSIGN, std::move(wire), std::move($3)); + SET_AST_NODE_LOC(assign.get(), @1, @3); + ast_stack.back()->children.push_back(std::move(assign)); } }; @@ -2058,18 +2041,18 @@ wire_name: TOK_ID range_or_multirange { if (astbuf1 == nullptr) frontend_verilog_yyerror("Internal error - should not happen - no AST_WIRE node."); - AstNode *node = astbuf1->clone(); + auto node = astbuf1->clone(); node->str = *$1; - append_attr_clone(node, albuf); - if (astbuf2 != NULL) + append_attr_clone(node.get(), albuf); + if (astbuf2 != nullptr) node->children.push_back(astbuf2->clone()); - if ($2 != NULL) { + if ($2 != nullptr) { if (node->is_input || node->is_output) frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions."); if (!astbuf2 && !node->is_custom_type) { - addRange(node, 0, 0, false); + addRange(node.get(), 0, 0, false); } - rewriteAsMemoryNode(node, $2); + rewriteAsMemoryNode(node.get(), std::move($2)); } if (current_function_or_task) { if (node->is_input || node->is_output) @@ -2094,55 +2077,55 @@ wire_name: } } //FIXME: for some reason, TOK_ID has a location which always points to one column *after* the real last column... - SET_AST_NODE_LOC(node, @1, @1); - ast_stack.back()->children.push_back(node); + SET_AST_NODE_LOC(node.get(), @1, @1); + ast_stack.back()->children.push_back(std::move(node)); - delete $1; }; assign_stmt: - TOK_ASSIGN delay assign_expr_list ';'; + TOK_ASSIGN delay assign_expr_list TOK_SEMICOL; assign_expr_list: - assign_expr | assign_expr_list ',' assign_expr; + assign_expr | assign_expr_list TOK_COMMA assign_expr; assign_expr: - lvalue '=' expr { - AstNode *node = new AstNode(AST_ASSIGN, $1, $3); + lvalue TOK_EQ expr { + AstNode* node = saveChild(std::make_unique(AST_ASSIGN, std::move($1), std::move($3))); SET_AST_NODE_LOC(node, @$, @$); - ast_stack.back()->children.push_back(node); }; type_name: TOK_ID // first time seen - | TOK_USER_TYPE { if (isInLocalScope($1)) frontend_verilog_yyerror("Duplicate declaration of TYPEDEF '%s'", $1->c_str()+1); } + | TOK_USER_TYPE { if (isInLocalScope($1)) frontend_verilog_yyerror("Duplicate declaration of TYPEDEF '%s'", $1->c_str()+1); $$ = std::move($1); } ; typedef_decl: - TOK_TYPEDEF typedef_base_type range_or_multirange type_name range_or_multirange ';' { - astbuf1 = $2; - astbuf2 = checkRange(astbuf1, $3); - if (astbuf2) - astbuf1->children.push_back(astbuf2); - - if ($5 != NULL) { - if (!astbuf2 && !astbuf1->is_custom_type) { - addRange(astbuf1, 0, 0, false); - } - rewriteAsMemoryNode(astbuf1, $5); + TOK_TYPEDEF typedef_base_type range_or_multirange type_name range_or_multirange TOK_SEMICOL { + astbuf1 = std::move($2); + astbuf2 = checkRange(astbuf1.get(), std::move($3)); + bool has_a_range = (bool)astbuf2; + if (astbuf2) { + astbuf1->children.push_back(std::move(astbuf2)); } - addTypedefNode($4, astbuf1); } - | TOK_TYPEDEF enum_struct_type type_name ';' { addTypedefNode($3, $2); } + + if ($5 != nullptr) { + if (!has_a_range && !astbuf1->is_custom_type) { + addRange(astbuf1.get(), 0, 0, false); + } + rewriteAsMemoryNode(astbuf1.get(), std::move($5)); + } + addTypedefNode($4, std::move(astbuf1)); } + | TOK_TYPEDEF enum_struct_type type_name TOK_SEMICOL { addTypedefNode($3, std::move($2)); } ; typedef_base_type: hierarchical_type_id { - $$ = new AstNode(AST_WIRE); + $$ = std::make_unique(AST_WIRE); $$->is_logic = true; - addWiretypeNode($1, $$); + addWiretypeNode($1, $$.get()); } | integer_vector_type opt_signedness_default_unsigned { - $$ = new AstNode(AST_WIRE); - if ($1 == TOK_REG) { + $$ = std::make_unique(AST_WIRE); + if ($1 == token::TOK_REG) { $$->is_reg = true; } else { $$->is_logic = true; @@ -2150,7 +2133,7 @@ typedef_base_type: $$->is_signed = $2; } | integer_atom_type opt_signedness_default_signed { - $$ = new AstNode(AST_WIRE); + $$ = std::make_unique(AST_WIRE); $$->is_logic = true; $$->is_signed = $2; $$->range_left = $1 - 1; @@ -2158,27 +2141,25 @@ typedef_base_type: }; enum_struct_type: - enum_type - | struct_type + enum_type { $$ = std::move($1); } + | struct_type { $$ = std::move($1); } ; cell_stmt: attr TOK_ID { - astbuf1 = new AstNode(AST_CELL); - append_attr(astbuf1, $1); - astbuf1->children.push_back(new AstNode(AST_CELLTYPE)); + astbuf1 = std::make_unique(AST_CELL); + append_attr(astbuf1.get(), $1); + astbuf1->children.push_back(std::make_unique(AST_CELLTYPE)); astbuf1->children[0]->str = *$2; - delete $2; - } cell_parameter_list_opt cell_list ';' { - delete astbuf1; + } cell_parameter_list_opt cell_list TOK_SEMICOL { + (void)astbuf1.reset(); } | attr tok_prim_wrapper delay { - astbuf1 = new AstNode(AST_PRIMITIVE); + astbuf1 = std::make_unique(AST_PRIMITIVE); astbuf1->str = *$2; - append_attr(astbuf1, $1); - delete $2; - } prim_list ';' { - delete astbuf1; + append_attr(astbuf1.get(), $1); + } prim_list TOK_SEMICOL { + (void)astbuf1.reset(); }; tok_prim_wrapper: @@ -2191,7 +2172,7 @@ tok_prim_wrapper: cell_list: single_cell | - cell_list ',' single_cell; + cell_list TOK_COMMA single_cell; single_cell: single_cell_no_array | single_cell_arraylist; @@ -2201,10 +2182,13 @@ single_cell_no_array: astbuf2 = astbuf1->clone(); if (astbuf2->type != AST_PRIMITIVE) astbuf2->str = *$1; - delete $1; - ast_stack.back()->children.push_back(astbuf2); - } '(' cell_port_list ')' { - SET_AST_NODE_LOC(astbuf2, @1, @$); + // TODO optimize again + cell_hack = astbuf2.get(); + ast_stack.back()->children.push_back(std::move(astbuf2)); + } TOK_LPAREN cell_port_list TOK_RPAREN { + log_assert(cell_hack); + SET_AST_NODE_LOC(cell_hack, @1, @$); + cell_hack = nullptr; } single_cell_arraylist: @@ -2212,70 +2196,75 @@ single_cell_arraylist: astbuf2 = astbuf1->clone(); if (astbuf2->type != AST_PRIMITIVE) astbuf2->str = *$1; - delete $1; - ast_stack.back()->children.push_back(new AstNode(AST_CELLARRAY, $2, astbuf2)); - } '(' cell_port_list ')'{ - SET_AST_NODE_LOC(astbuf2, @1, @$); + // TODO optimize again + cell_hack = astbuf2.get(); + ast_stack.back()->children.push_back(std::make_unique(AST_CELLARRAY, std::move($2), std::move(astbuf2))); + } TOK_LPAREN cell_port_list TOK_RPAREN{ + log_assert(cell_hack); + SET_AST_NODE_LOC(cell_hack, @1, @$); + cell_hack = nullptr; }; cell_list_no_array: single_cell_no_array | - cell_list_no_array ',' single_cell_no_array; + cell_list_no_array TOK_COMMA single_cell_no_array; prim_list: single_prim | - prim_list ',' single_prim; + prim_list TOK_COMMA single_prim; single_prim: single_cell | /* no name */ { astbuf2 = astbuf1->clone(); - ast_stack.back()->children.push_back(astbuf2); - } '(' cell_port_list ')' { - SET_AST_NODE_LOC(astbuf2, @1, @$); + log_assert(!cell_hack); + cell_hack = astbuf2.get(); + // TODO optimize again + ast_stack.back()->children.push_back(std::move(astbuf2)); + } TOK_LPAREN cell_port_list TOK_RPAREN { + log_assert(cell_hack); + SET_AST_NODE_LOC(cell_hack, @1, @$); + cell_hack = nullptr; } cell_parameter_list_opt: - '#' '(' cell_parameter_list ')' | %empty; + TOK_HASH TOK_LPAREN cell_parameter_list TOK_RPAREN | %empty; cell_parameter_list: - cell_parameter | cell_parameter_list ',' cell_parameter; + cell_parameter | cell_parameter_list TOK_COMMA cell_parameter; cell_parameter: %empty | expr { - AstNode *node = new AstNode(AST_PARASET); - astbuf1->children.push_back(node); - node->children.push_back($1); + auto node = std::make_unique(AST_PARASET); + node->children.push_back(std::move($1)); + astbuf1->children.push_back(std::move(node)); } | - '.' TOK_ID '(' ')' { - // delete unused TOK_ID - delete $2; + TOK_DOT TOK_ID TOK_LPAREN TOK_RPAREN { + // just ignore empty parameters } | - '.' TOK_ID '(' expr ')' { - AstNode *node = new AstNode(AST_PARASET); + TOK_DOT TOK_ID TOK_LPAREN expr TOK_RPAREN { + auto node = std::make_unique(AST_PARASET); node->str = *$2; - astbuf1->children.push_back(node); - node->children.push_back($4); - delete $2; + node->children.push_back(std::move($4)); + astbuf1->children.push_back(std::move(node)); }; cell_port_list: cell_port_list_rules { // remove empty args from end of list - while (!astbuf2->children.empty()) { - AstNode *node = astbuf2->children.back(); + while (!cell_hack->children.empty()) { + auto& node = cell_hack->children.back(); if (node->type != AST_ARGUMENT) break; if (!node->children.empty()) break; if (!node->str.empty()) break; - astbuf2->children.pop_back(); - delete node; + cell_hack->children.pop_back(); } // check port types bool has_positional_args = false; bool has_named_args = false; - for (auto node : astbuf2->children) { + for (auto& node : cell_hack->children) { if (node->type != AST_ARGUMENT) continue; if (node->str.empty()) has_positional_args = true; @@ -2288,48 +2277,45 @@ cell_port_list: }; cell_port_list_rules: - cell_port | cell_port_list_rules ',' cell_port; + cell_port | cell_port_list_rules TOK_COMMA cell_port; cell_port: attr { - AstNode *node = new AstNode(AST_ARGUMENT); - astbuf2->children.push_back(node); + auto node = std::make_unique(AST_ARGUMENT); + cell_hack->children.push_back(std::move(node)); free_attr($1); } | attr expr { - AstNode *node = new AstNode(AST_ARGUMENT); - astbuf2->children.push_back(node); - node->children.push_back($2); + auto node = std::make_unique(AST_ARGUMENT); + node->children.push_back(std::move($2)); + cell_hack->children.push_back(std::move(node)); free_attr($1); } | - attr '.' TOK_ID '(' expr ')' { - AstNode *node = new AstNode(AST_ARGUMENT); + attr TOK_DOT TOK_ID TOK_LPAREN expr TOK_RPAREN { + auto node = std::make_unique(AST_ARGUMENT); node->str = *$3; - astbuf2->children.push_back(node); - node->children.push_back($5); - delete $3; + node->children.push_back(std::move($5)); + cell_hack->children.push_back(std::move(node)); free_attr($1); } | - attr '.' TOK_ID '(' ')' { - AstNode *node = new AstNode(AST_ARGUMENT); + attr TOK_DOT TOK_ID TOK_LPAREN TOK_RPAREN { + auto node = std::make_unique(AST_ARGUMENT); node->str = *$3; - astbuf2->children.push_back(node); - delete $3; + cell_hack->children.push_back(std::move(node)); free_attr($1); } | - attr '.' TOK_ID { - AstNode *node = new AstNode(AST_ARGUMENT); + attr TOK_DOT TOK_ID { + auto node = std::make_unique(AST_ARGUMENT); node->str = *$3; - astbuf2->children.push_back(node); - node->children.push_back(new AstNode(AST_IDENTIFIER)); + node->children.push_back(std::make_unique(AST_IDENTIFIER)); node->children.back()->str = *$3; - delete $3; + cell_hack->children.push_back(std::move(node)); free_attr($1); } | attr TOK_WILDCARD_CONNECT { if (!sv_mode) frontend_verilog_yyerror("Wildcard port connections are only supported in SystemVerilog mode."); - astbuf2->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(1, false); + cell_hack->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(1, false); free_attr($1); }; @@ -2351,16 +2337,12 @@ always_or_always_ff: always_stmt: attr always_or_always_ff { - AstNode *node = new AstNode(AST_ALWAYS); + AstNode* node = pushChild(std::make_unique(AST_ALWAYS)); append_attr(node, $1); if ($2) node->attributes[ID::always_ff] = AstNode::mkconst_int(1, false); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); } always_cond { - AstNode *block = new AstNode(AST_BLOCK); - ast_stack.back()->children.push_back(block); - ast_stack.push_back(block); + (void)pushChild(std::make_unique(AST_BLOCK)); } behavioral_stmt { SET_AST_NODE_LOC(ast_stack.back(), @6, @6); ast_stack.pop_back(); @@ -2371,80 +2353,72 @@ always_stmt: SET_RULE_LOC(@$, @2, @$); } | attr always_comb_or_latch { - AstNode *node = new AstNode(AST_ALWAYS); + AstNode* node = pushChild(std::make_unique(AST_ALWAYS)); append_attr(node, $1); if ($2) node->attributes[ID::always_latch] = AstNode::mkconst_int(1, false); else node->attributes[ID::always_comb] = AstNode::mkconst_int(1, false); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); - AstNode *block = new AstNode(AST_BLOCK); - ast_stack.back()->children.push_back(block); - ast_stack.push_back(block); + (void)pushChild(std::make_unique(AST_BLOCK)); } behavioral_stmt { ast_stack.pop_back(); ast_stack.pop_back(); } | attr TOK_INITIAL { - AstNode *node = new AstNode(AST_INITIAL); + AstNode* node = pushChild(std::make_unique(AST_INITIAL)); append_attr(node, $1); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); - AstNode *block = new AstNode(AST_BLOCK); - ast_stack.back()->children.push_back(block); - ast_stack.push_back(block); + (void)pushChild(std::make_unique(AST_BLOCK)); } behavioral_stmt { ast_stack.pop_back(); ast_stack.pop_back(); }; always_cond: - '@' '(' always_events ')' | - '@' '(' '*' ')' | - '@' ATTR_BEGIN ')' | - '@' '(' ATTR_END | - '@' '*' | + TOK_AT TOK_LPAREN always_events TOK_RPAREN | + TOK_AT TOK_LPAREN TOK_ASTER TOK_RPAREN | + TOK_AT ATTR_BEGIN TOK_RPAREN | + TOK_AT TOK_LPAREN ATTR_END | + TOK_AT TOK_ASTER | %empty; always_events: always_event | always_events TOK_OR always_event | - always_events ',' always_event; + always_events TOK_COMMA always_event; always_event: TOK_POSEDGE expr { - AstNode *node = new AstNode(AST_POSEDGE); - SET_AST_NODE_LOC(node, @1, @1); - ast_stack.back()->children.push_back(node); - node->children.push_back($2); + auto node = std::make_unique(AST_POSEDGE); + SET_AST_NODE_LOC(node.get(), @1, @1); + node->children.push_back(std::move($2)); + ast_stack.back()->children.push_back(std::move(node)); } | TOK_NEGEDGE expr { - AstNode *node = new AstNode(AST_NEGEDGE); - SET_AST_NODE_LOC(node, @1, @1); - ast_stack.back()->children.push_back(node); - node->children.push_back($2); + auto node = std::make_unique(AST_NEGEDGE); + SET_AST_NODE_LOC(node.get(), @1, @1); + node->children.push_back(std::move($2)); + ast_stack.back()->children.push_back(std::move(node)); } | expr { - AstNode *node = new AstNode(AST_EDGE); - ast_stack.back()->children.push_back(node); - node->children.push_back($1); + auto node = std::make_unique(AST_EDGE); + node->children.push_back(std::move($1)); + ast_stack.back()->children.push_back(std::move(node)); }; opt_label: - ':' TOK_ID { + TOK_COL TOK_ID { $$ = $2; } | %empty { - $$ = NULL; + $$ = nullptr; }; opt_sva_label: - TOK_SVA_LABEL ':' { + TOK_SVA_LABEL TOK_COL { $$ = $1; } | %empty { - $$ = NULL; + $$ = nullptr; }; opt_property: @@ -2460,21 +2434,19 @@ opt_property: modport_stmt: TOK_MODPORT TOK_ID { - AstNode *modport = new AstNode(AST_MODPORT); - ast_stack.back()->children.push_back(modport); - ast_stack.push_back(modport); + AstNode* modport = pushChild(std::make_unique(AST_MODPORT)); modport->str = *$2; - delete $2; + } modport_args_opt { ast_stack.pop_back(); log_assert(ast_stack.size() == 2); - } ';' + } TOK_SEMICOL modport_args_opt: - '(' ')' | '(' modport_args optional_comma ')'; + TOK_LPAREN TOK_RPAREN | TOK_LPAREN modport_args optional_comma TOK_RPAREN; modport_args: - modport_arg | modport_args ',' modport_arg; + modport_arg | modport_args TOK_COMMA modport_arg; modport_arg: modport_type_token modport_member | @@ -2482,222 +2454,174 @@ modport_arg: modport_member: TOK_ID { - AstNode *modport_member = new AstNode(AST_MODPORTMEMBER); - ast_stack.back()->children.push_back(modport_member); + AstNode* modport_member = saveChild(std::make_unique(AST_MODPORTMEMBER)); modport_member->str = *$1; modport_member->is_input = current_modport_input; modport_member->is_output = current_modport_output; - delete $1; + } modport_type_token: TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} assert: - opt_sva_label TOK_ASSERT opt_property '(' expr ')' ';' { + opt_sva_label TOK_ASSERT opt_property TOK_LPAREN expr TOK_RPAREN TOK_SEMICOL { if (noassert_mode) { - delete $5; + } else { - AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); + AstNode* node = saveChild(std::make_unique(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, std::move($5))); SET_AST_NODE_LOC(node, ($1 != nullptr ? @1 : @2), @6); if ($1 != nullptr) node->str = *$1; - ast_stack.back()->children.push_back(node); } - if ($1 != nullptr) - delete $1; } | - opt_sva_label TOK_ASSUME opt_property '(' expr ')' ';' { + opt_sva_label TOK_ASSUME opt_property TOK_LPAREN expr TOK_RPAREN TOK_SEMICOL { if (noassume_mode) { - delete $5; } else { - AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5); + AstNode* node = saveChild(std::make_unique(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, std::move($5))); SET_AST_NODE_LOC(node, ($1 != nullptr ? @1 : @2), @6); if ($1 != nullptr) node->str = *$1; - ast_stack.back()->children.push_back(node); } - if ($1 != nullptr) - delete $1; } | - opt_sva_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_ASSERT opt_property TOK_LPAREN TOK_EVENTUALLY expr TOK_RPAREN TOK_SEMICOL { if (noassert_mode) { - delete $6; } else { - AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); + AstNode* node = saveChild(std::make_unique(assume_asserts_mode ? AST_FAIR : AST_LIVE, std::move($6))); SET_AST_NODE_LOC(node, ($1 != nullptr ? @1 : @2), @7); if ($1 != nullptr) node->str = *$1; - ast_stack.back()->children.push_back(node); } - if ($1 != nullptr) - delete $1; } | - opt_sva_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_ASSUME opt_property TOK_LPAREN TOK_EVENTUALLY expr TOK_RPAREN TOK_SEMICOL { if (noassume_mode) { - delete $6; } else { - AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6); + AstNode* node = saveChild(std::make_unique(assert_assumes_mode ? AST_LIVE : AST_FAIR, std::move($6))); SET_AST_NODE_LOC(node, ($1 != nullptr ? @1 : @2), @7); if ($1 != nullptr) node->str = *$1; - ast_stack.back()->children.push_back(node); } - if ($1 != nullptr) - delete $1; } | - opt_sva_label TOK_COVER opt_property '(' expr ')' ';' { - AstNode *node = new AstNode(AST_COVER, $5); + opt_sva_label TOK_COVER opt_property TOK_LPAREN expr TOK_RPAREN TOK_SEMICOL { + AstNode* node = saveChild(std::make_unique(AST_COVER, std::move($5))); SET_AST_NODE_LOC(node, ($1 != nullptr ? @1 : @2), @6); if ($1 != nullptr) { node->str = *$1; - delete $1; } - ast_stack.back()->children.push_back(node); } | - opt_sva_label TOK_COVER opt_property '(' ')' ';' { - AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); + opt_sva_label TOK_COVER opt_property TOK_LPAREN TOK_RPAREN TOK_SEMICOL { + AstNode* node = saveChild(std::make_unique(AST_COVER, AstNode::mkconst_int(1, false))); SET_AST_NODE_LOC(node, ($1 != nullptr ? @1 : @2), @5); if ($1 != nullptr) { node->str = *$1; - delete $1; } - ast_stack.back()->children.push_back(node); } | - opt_sva_label TOK_COVER ';' { - AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); + opt_sva_label TOK_COVER TOK_SEMICOL { + AstNode* node = saveChild(std::make_unique(AST_COVER, AstNode::mkconst_int(1, false))); SET_AST_NODE_LOC(node, ($1 != nullptr ? @1 : @2), @2); if ($1 != nullptr) { node->str = *$1; - delete $1; } - ast_stack.back()->children.push_back(node); } | - opt_sva_label TOK_RESTRICT opt_property '(' expr ')' ';' { + opt_sva_label TOK_RESTRICT opt_property TOK_LPAREN expr TOK_RPAREN TOK_SEMICOL { if (norestrict_mode) { - delete $5; } else { - AstNode *node = new AstNode(AST_ASSUME, $5); + AstNode* node = saveChild(std::make_unique(AST_ASSUME, std::move($5))); SET_AST_NODE_LOC(node, ($1 != nullptr ? @1 : @2), @6); if ($1 != nullptr) node->str = *$1; - ast_stack.back()->children.push_back(node); } if (!$3) - log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); - if ($1 != nullptr) - delete $1; + log_file_warning(current_filename, @$.begin.line, "SystemVerilog does not allow \"restrict\" without \"property\".\n"); } | - opt_sva_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_RESTRICT opt_property TOK_LPAREN TOK_EVENTUALLY expr TOK_RPAREN TOK_SEMICOL { if (norestrict_mode) { - delete $6; } else { - AstNode *node = new AstNode(AST_FAIR, $6); + AstNode* node = saveChild(std::make_unique(AST_FAIR, std::move($6))); SET_AST_NODE_LOC(node, ($1 != nullptr ? @1 : @2), @7); if ($1 != nullptr) node->str = *$1; - ast_stack.back()->children.push_back(node); } if (!$3) - log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); - if ($1 != nullptr) - delete $1; + log_file_warning(current_filename, @$.begin.line, "SystemVerilog does not allow \"restrict\" without \"property\".\n"); }; assert_property: - opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { - AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); + opt_sva_label TOK_ASSERT TOK_PROPERTY TOK_LPAREN expr TOK_RPAREN TOK_SEMICOL { + AstNode* node = saveChild(std::make_unique(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, std::move($5))); SET_AST_NODE_LOC(node, @1, @6); - ast_stack.back()->children.push_back(node); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; - delete $1; } } | - opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { - AstNode *node = new AstNode(AST_ASSUME, $5); + opt_sva_label TOK_ASSUME TOK_PROPERTY TOK_LPAREN expr TOK_RPAREN TOK_SEMICOL { + AstNode* node = saveChild(std::make_unique(AST_ASSUME, std::move($5))); SET_AST_NODE_LOC(node, @1, @6); - ast_stack.back()->children.push_back(node); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; - delete $1; } } | - opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { - AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); + opt_sva_label TOK_ASSERT TOK_PROPERTY TOK_LPAREN TOK_EVENTUALLY expr TOK_RPAREN TOK_SEMICOL { + AstNode* node = saveChild(std::make_unique(assume_asserts_mode ? AST_FAIR : AST_LIVE, std::move($6))); SET_AST_NODE_LOC(node, @1, @7); - ast_stack.back()->children.push_back(node); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; - delete $1; } } | - opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { - AstNode *node = new AstNode(AST_FAIR, $6); + opt_sva_label TOK_ASSUME TOK_PROPERTY TOK_LPAREN TOK_EVENTUALLY expr TOK_RPAREN TOK_SEMICOL { + AstNode* node = saveChild(std::make_unique(AST_FAIR, std::move($6))); SET_AST_NODE_LOC(node, @1, @7); - ast_stack.back()->children.push_back(node); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; - delete $1; } } | - opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' { - AstNode *node = new AstNode(AST_COVER, $5); + opt_sva_label TOK_COVER TOK_PROPERTY TOK_LPAREN expr TOK_RPAREN TOK_SEMICOL { + AstNode* node = saveChild(std::make_unique(AST_COVER, std::move($5))); SET_AST_NODE_LOC(node, @1, @6); - ast_stack.back()->children.push_back(node); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; - delete $1; } } | - opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { + opt_sva_label TOK_RESTRICT TOK_PROPERTY TOK_LPAREN expr TOK_RPAREN TOK_SEMICOL { if (norestrict_mode) { - delete $5; } else { - AstNode *node = new AstNode(AST_ASSUME, $5); + AstNode* node = saveChild(std::make_unique(AST_ASSUME, std::move($5))); SET_AST_NODE_LOC(node, @1, @6); - ast_stack.back()->children.push_back(node); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; - delete $1; } } } | - opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_RESTRICT TOK_PROPERTY TOK_LPAREN TOK_EVENTUALLY expr TOK_RPAREN TOK_SEMICOL { if (norestrict_mode) { - delete $6; } else { - AstNode *node = new AstNode(AST_FAIR, $6); + AstNode* node = saveChild(std::make_unique(AST_FAIR, std::move($6))); SET_AST_NODE_LOC(node, @1, @7); - ast_stack.back()->children.push_back(node); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; - delete $1; } } }; simple_behavioral_stmt: - attr lvalue '=' delay expr { - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, $5); - ast_stack.back()->children.push_back(node); + attr lvalue TOK_EQ delay expr { + AstNode* node = saveChild(std::make_unique(AST_ASSIGN_EQ, std::move($2), std::move($5))); SET_AST_NODE_LOC(node, @2, @5); append_attr(node, $1); } | attr lvalue attr inc_or_dec_op { - addIncOrDecStmt($1, $2, $3, $4, @1, @4); + addIncOrDecStmt($1, std::move($2), $3, $4, @1, @4); } | attr inc_or_dec_op attr lvalue { - addIncOrDecStmt($1, $4, $3, $2, @1, @4); + addIncOrDecStmt($1, std::move($4), $3, $2, @1, @4); } | attr lvalue OP_LE delay expr { - AstNode *node = new AstNode(AST_ASSIGN_LE, $2, $5); - ast_stack.back()->children.push_back(node); + AstNode* node = saveChild(std::make_unique(AST_ASSIGN_LE, std::move($2), std::move($5))); SET_AST_NODE_LOC(node, @2, @5); append_attr(node, $1); } | attr lvalue asgn_binop delay expr { - addAsgnBinopStmt($1, $2, $3, $5, @2, @5); + (void)addAsgnBinopStmt($1, std::move($2), $3, std::move($5), @2, @5); }; asgn_binop: @@ -2721,91 +2645,81 @@ inc_or_dec_op: TOK_DECREMENT { $$ = AST_SUB; } ; for_initialization: - TOK_ID '=' expr { - AstNode *ident = new AstNode(AST_IDENTIFIER); + TOK_ID TOK_EQ expr { + auto ident = std::make_unique(AST_IDENTIFIER); ident->str = *$1; - AstNode *node = new AstNode(AST_ASSIGN_EQ, ident, $3); - ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @1, @3); - delete $1; + auto node = std::make_unique(AST_ASSIGN_EQ, std::move(ident), std::move($3)); + SET_AST_NODE_LOC(node.get(), @1, @3); + ast_stack.back()->children.push_back(std::move(node)); } | non_io_wire_type range TOK_ID { frontend_verilog_yyerror("For loop variable declaration is missing initialization!"); } | - non_io_wire_type range TOK_ID '=' expr { + non_io_wire_type range TOK_ID TOK_EQ expr { if (!sv_mode) frontend_verilog_yyerror("For loop inline variable declaration is only supported in SystemVerilog mode!"); // loop variable declaration - AstNode *wire = $1; - AstNode *range = checkRange(wire, $2); + auto wire = std::move($1); + auto range = checkRange(wire.get(), std::move($2)); + SET_AST_NODE_LOC(wire.get(), @1, @3); + SET_AST_NODE_LOC(range.get(), @2, @2); if (range != nullptr) - wire->children.push_back(range); - SET_AST_NODE_LOC(wire, @1, @3); - SET_AST_NODE_LOC(range, @2, @2); + wire->children.push_back(std::move(range)); - AstNode *ident = new AstNode(AST_IDENTIFIER); + auto ident = std::make_unique(AST_IDENTIFIER); ident->str = *$3; wire->str = *$3; - delete $3; - AstNode *loop = ast_stack.back(); AstNode *parent = ast_stack.at(ast_stack.size() - 2); - log_assert(parent->children.back() == loop); + auto& loop = parent->children.back(); + log_assert(ast_stack.back() == loop.get()); // loop variable initialization - AstNode *asgn = new AstNode(AST_ASSIGN_EQ, ident, $5); - loop->children.push_back(asgn); - SET_AST_NODE_LOC(asgn, @3, @5); - SET_AST_NODE_LOC(ident, @3, @3); + SET_AST_NODE_LOC(ident.get(), @3, @3); + auto asgn = std::make_unique(AST_ASSIGN_EQ, std::move(ident), std::move($5)); + SET_AST_NODE_LOC(asgn.get(), @3, @5); + loop->children.push_back(std::move(asgn)); // inject a wrapping block to declare the loop variable and // contain the current loop - AstNode *wrapper = new AstNode(AST_BLOCK); + auto wrapper = std::make_unique(AST_BLOCK); wrapper->str = "$fordecl_block$" + std::to_string(autoidx++); - wrapper->children.push_back(wire); - wrapper->children.push_back(loop); - parent->children.back() = wrapper; // replaces `loop` + wrapper->children.push_back(std::move(wire)); + wrapper->children.push_back(std::move(loop)); + parent->children.back() = std::move(wrapper); }; // this production creates the obligatory if-else shift/reduce conflict behavioral_stmt: defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl | non_opt_delay behavioral_stmt | - simple_behavioral_stmt ';' | - attr ';' { + simple_behavioral_stmt TOK_SEMICOL | + attr TOK_SEMICOL { free_attr($1); } | attr hierarchical_id { - AstNode *node = new AstNode(AST_TCALL); + AstNode* node = pushChild(std::make_unique(AST_TCALL)); node->str = *$2; - delete $2; - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); append_attr(node, $1); - } opt_arg_list ';'{ + } opt_arg_list TOK_SEMICOL{ SET_AST_NODE_LOC(ast_stack.back(), @2, @5); ast_stack.pop_back(); } | attr TOK_MSG_TASKS { - AstNode *node = new AstNode(AST_TCALL); + AstNode* node = pushChild(std::make_unique(AST_TCALL)); node->str = *$2; - delete $2; - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); append_attr(node, $1); - } opt_arg_list ';'{ + } opt_arg_list TOK_SEMICOL{ SET_AST_NODE_LOC(ast_stack.back(), @2, @5); ast_stack.pop_back(); } | attr TOK_BEGIN { enterTypeScope(); } opt_label { - AstNode *node = new AstNode(AST_BLOCK); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); + AstNode* node = pushChild(std::make_unique(AST_BLOCK)); append_attr(node, $1); - if ($4 != NULL) + if ($4 != nullptr) node->str = *$4; } behavioral_stmt_list TOK_END opt_label { exitTypeScope(); @@ -2814,71 +2728,65 @@ behavioral_stmt: // In SystemVerilog, unnamed blocks with block item declarations // create an implicit hierarchy scope if (sv_mode && node->str.empty()) - for (const AstNode* child : node->children) + for (auto& child : node->children) if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_TYPEDEF) { node->str = "$unnamed_block$" + std::to_string(autoidx++); break; } SET_AST_NODE_LOC(ast_stack.back(), @2, @8); - delete $4; - delete $8; ast_stack.pop_back(); } | - attr TOK_FOR '(' { - AstNode *node = new AstNode(AST_FOR); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); + attr TOK_FOR TOK_LPAREN { + AstNode* node = pushChild(std::make_unique(AST_FOR)); append_attr(node, $1); - } for_initialization ';' expr { - ast_stack.back()->children.push_back($7); - } ';' simple_behavioral_stmt ')' { - AstNode *block = new AstNode(AST_BLOCK); + } for_initialization TOK_SEMICOL expr { + ast_stack.back()->children.push_back(std::move($7)); + } TOK_SEMICOL simple_behavioral_stmt TOK_RPAREN { + AstNode* block = pushChild(std::make_unique(AST_BLOCK)); block->str = "$for_loop$" + std::to_string(autoidx++); - ast_stack.back()->children.push_back(block); - ast_stack.push_back(block); } behavioral_stmt { SET_AST_NODE_LOC(ast_stack.back(), @13, @13); ast_stack.pop_back(); SET_AST_NODE_LOC(ast_stack.back(), @2, @13); ast_stack.pop_back(); } | - attr TOK_WHILE '(' expr ')' { - AstNode *node = new AstNode(AST_WHILE); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); + attr TOK_WHILE TOK_LPAREN expr TOK_RPAREN { + AstNode* node = pushChild(std::make_unique(AST_WHILE)); append_attr(node, $1); - AstNode *block = new AstNode(AST_BLOCK); - ast_stack.back()->children.push_back($4); - ast_stack.back()->children.push_back(block); + auto block_owned = std::make_unique(AST_BLOCK); + auto* block = block_owned.get(); + ast_stack.back()->children.push_back(std::move($4)); + ast_stack.back()->children.push_back(std::move(block_owned)); ast_stack.push_back(block); } behavioral_stmt { SET_AST_NODE_LOC(ast_stack.back(), @7, @7); ast_stack.pop_back(); ast_stack.pop_back(); } | - attr TOK_REPEAT '(' expr ')' { - AstNode *node = new AstNode(AST_REPEAT); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); + attr TOK_REPEAT TOK_LPAREN expr TOK_RPAREN { + AstNode* node = pushChild(std::make_unique(AST_REPEAT)); append_attr(node, $1); - AstNode *block = new AstNode(AST_BLOCK); - ast_stack.back()->children.push_back($4); - ast_stack.back()->children.push_back(block); + auto block_owned = std::make_unique(AST_BLOCK); + auto* block = block_owned.get(); + ast_stack.back()->children.push_back(std::move($4)); + ast_stack.back()->children.push_back(std::move(block_owned)); ast_stack.push_back(block); } behavioral_stmt { SET_AST_NODE_LOC(ast_stack.back(), @7, @7); ast_stack.pop_back(); ast_stack.pop_back(); } | - attr TOK_IF '(' expr ')' { - AstNode *node = new AstNode(AST_CASE); - AstNode *block = new AstNode(AST_BLOCK); - AstNode *cond = new AstNode(AST_COND, AstNode::mkconst_int(1, false, 1), block); - SET_AST_NODE_LOC(cond, @4, @4); - ast_stack.back()->children.push_back(node); - node->children.push_back(new AstNode(AST_REDUCE_BOOL, $4)); - node->children.push_back(cond); + attr TOK_IF TOK_LPAREN expr TOK_RPAREN { + auto node_owned = std::make_unique(AST_CASE); + auto* node = node_owned.get(); + auto block_owned = std::make_unique(AST_BLOCK); + auto* block = block_owned.get(); + auto cond_owned = std::make_unique(AST_COND, AstNode::mkconst_int(1, false, 1), std::move(block_owned)); + SET_AST_NODE_LOC(cond_owned.get(), @4, @4); + ast_stack.back()->children.push_back(std::move(node_owned)); + node->children.push_back(std::make_unique(AST_REDUCE_BOOL, std::move($4))); + node->children.push_back(std::move(cond_owned)); ast_stack.push_back(node); ast_stack.push_back(block); append_attr(node, $1); @@ -2889,10 +2797,8 @@ behavioral_stmt: SET_AST_NODE_LOC(ast_stack.back(), @2, @9); ast_stack.pop_back(); } | - case_attr case_type '(' expr ')' { - AstNode *node = new AstNode(AST_CASE, $4); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); + case_attr case_type TOK_LPAREN expr TOK_RPAREN { + AstNode* node = pushChild(std::make_unique(AST_CASE, std::move($4))); append_attr(node, $1); SET_AST_NODE_LOC(ast_stack.back(), @4, @4); } opt_synopsys_attr case_body TOK_ENDCASE { @@ -2947,13 +2853,15 @@ behavioral_stmt_list: optional_else: TOK_ELSE { - AstNode *block = new AstNode(AST_BLOCK); - AstNode *cond = new AstNode(AST_COND, new AstNode(AST_DEFAULT), block); - SET_AST_NODE_LOC(cond, @1, @1); - ast_stack.pop_back(); - ast_stack.back()->children.push_back(cond); + auto block_owned = std::make_unique(AST_BLOCK); + auto* block = block_owned.get(); + AstNode* cond = saveChild( + std::make_unique(AST_COND, + std::make_unique(AST_DEFAULT), + std::move(block_owned))); ast_stack.push_back(block); + SET_AST_NODE_LOC(cond, @1, @1); } behavioral_stmt { SET_AST_NODE_LOC(ast_stack.back(), @3, @3); } | @@ -2965,15 +2873,11 @@ case_body: case_item: { - AstNode *node = new AstNode( + (void)pushChild(std::make_unique( case_type_stack.size() && case_type_stack.back() == 'x' ? AST_CONDX : - case_type_stack.size() && case_type_stack.back() == 'z' ? AST_CONDZ : AST_COND); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); + case_type_stack.size() && case_type_stack.back() == 'z' ? AST_CONDZ : AST_COND)); } case_select { - AstNode *block = new AstNode(AST_BLOCK); - ast_stack.back()->children.push_back(block); - ast_stack.push_back(block); + (void)pushChild(std::make_unique(AST_BLOCK)); case_type_stack.push_back(0); } behavioral_stmt { case_type_stack.pop_back(); @@ -2988,11 +2892,9 @@ gen_case_body: gen_case_item: { - AstNode *node = new AstNode( + (void)pushChild(std::make_unique( case_type_stack.size() && case_type_stack.back() == 'x' ? AST_CONDX : - case_type_stack.size() && case_type_stack.back() == 'z' ? AST_CONDZ : AST_COND); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); + case_type_stack.size() && case_type_stack.back() == 'z' ? AST_CONDZ : AST_COND)); } case_select { case_type_stack.push_back(0); SET_AST_NODE_LOC(ast_stack.back(), @2, @2); @@ -3002,73 +2904,66 @@ gen_case_item: }; case_select: - case_expr_list ':' | + case_expr_list TOK_COL | TOK_DEFAULT; case_expr_list: TOK_DEFAULT { - AstNode *node = new AstNode(AST_DEFAULT); + AstNode* node = saveChild(std::make_unique(AST_DEFAULT)); SET_AST_NODE_LOC(node, @1, @1); - ast_stack.back()->children.push_back(node); } | TOK_SVA_LABEL { - AstNode *node = new AstNode(AST_IDENTIFIER); + AstNode* node = pushChild(std::make_unique(AST_IDENTIFIER)); SET_AST_NODE_LOC(node, @1, @1); - ast_stack.back()->children.push_back(node); - ast_stack.back()->children.back()->str = *$1; - delete $1; } | expr { - ast_stack.back()->children.push_back($1); + ast_stack.back()->children.push_back(std::move($1)); } | - case_expr_list ',' expr { - ast_stack.back()->children.push_back($3); + case_expr_list TOK_COMMA expr { + ast_stack.back()->children.push_back(std::move($3)); }; rvalue: - hierarchical_id '[' expr ']' '.' rvalue { - $$ = new AstNode(AST_PREFIX, $3, $6); + hierarchical_id TOK_LBRA expr TOK_RBRA TOK_DOT rvalue { + $$ = std::make_unique(AST_PREFIX, std::move($3), std::move($6)); $$->str = *$1; - SET_AST_NODE_LOC($$, @1, @6); - delete $1; + SET_AST_NODE_LOC($$.get(), @1, @6); } | hierarchical_id range { - $$ = new AstNode(AST_IDENTIFIER, $2); + $$ = std::make_unique(AST_IDENTIFIER, std::move($2)); $$->str = *$1; - SET_AST_NODE_LOC($$, @1, @1); - delete $1; + SET_AST_NODE_LOC($$.get(), @1, @1); if ($2 == nullptr && ($$->str == "\\$initstate" || $$->str == "\\$anyconst" || $$->str == "\\$anyseq" || $$->str == "\\$allconst" || $$->str == "\\$allseq")) $$->type = AST_FCALL; } | hierarchical_id non_opt_multirange { - $$ = new AstNode(AST_IDENTIFIER, $2); + $$ = std::make_unique(AST_IDENTIFIER, std::move($2)); $$->str = *$1; - SET_AST_NODE_LOC($$, @1, @1); - delete $1; + SET_AST_NODE_LOC($$.get(), @1, @1); }; lvalue: rvalue { - $$ = $1; + $$ = std::move($1); } | - '{' lvalue_concat_list '}' { - $$ = $2; + TOK_LCURL lvalue_concat_list TOK_RCURL { + $$ = std::move($2); }; lvalue_concat_list: expr { - $$ = new AstNode(AST_CONCAT); - $$->children.push_back($1); + $$ = std::make_unique(AST_CONCAT); + $$->children.push_back(std::move($1)); } | - expr ',' lvalue_concat_list { - $$ = $3; - $$->children.push_back($1); + expr TOK_COMMA lvalue_concat_list { + $$ = std::move($3); + $$->children.push_back(std::move($1)); }; opt_arg_list: - '(' arg_list optional_comma ')' | + TOK_LPAREN arg_list optional_comma TOK_RPAREN | %empty; arg_list: @@ -3077,11 +2972,11 @@ arg_list: arg_list2: single_arg | - arg_list ',' single_arg; + arg_list TOK_COMMA single_arg; single_arg: expr { - ast_stack.back()->children.push_back($1); + ast_stack.back()->children.push_back(std::move($1)); }; module_gen_body: @@ -3091,81 +2986,68 @@ module_gen_body: gen_stmt_or_module_body_stmt: gen_stmt | module_body_stmt | - attr ';' { + attr TOK_SEMICOL { free_attr($1); }; genvar_identifier: TOK_ID { - $$ = new AstNode(AST_IDENTIFIER); + $$ = std::make_unique(AST_IDENTIFIER); $$->str = *$1; - delete $1; }; genvar_initialization: TOK_GENVAR genvar_identifier { frontend_verilog_yyerror("Generate for loop variable declaration is missing initialization!"); } | - TOK_GENVAR genvar_identifier '=' expr { + TOK_GENVAR genvar_identifier TOK_EQ expr { if (!sv_mode) frontend_verilog_yyerror("Generate for loop inline variable declaration is only supported in SystemVerilog mode!"); - AstNode *node = new AstNode(AST_GENVAR); + AstNode* node = saveChild(std::make_unique(AST_GENVAR)); node->is_reg = true; node->is_signed = true; node->range_left = 31; node->range_right = 0; node->str = $2->str; node->children.push_back(checkRange(node, nullptr)); - ast_stack.back()->children.push_back(node); SET_AST_NODE_LOC(node, @1, @4); - node = new AstNode(AST_ASSIGN_EQ, $2, $4); - ast_stack.back()->children.push_back(node); + node = saveChild(std::make_unique(AST_ASSIGN_EQ, std::move($2), std::move($4))); SET_AST_NODE_LOC(node, @1, @4); } | - genvar_identifier '=' expr { - AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $3); - ast_stack.back()->children.push_back(node); + genvar_identifier TOK_EQ expr { + AstNode* node = saveChild(std::make_unique(AST_ASSIGN_EQ, std::move($1), std::move($3))); SET_AST_NODE_LOC(node, @1, @3); }; // this production creates the obligatory if-else shift/reduce conflict gen_stmt: - TOK_FOR '(' { - AstNode *node = new AstNode(AST_GENFOR); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); - } genvar_initialization ';' expr { - ast_stack.back()->children.push_back($6); - } ';' simple_behavioral_stmt ')' gen_stmt_block { + TOK_FOR TOK_LPAREN { + (void)pushChild(std::make_unique(AST_GENFOR)); + } genvar_initialization TOK_SEMICOL expr { + ast_stack.back()->children.push_back(std::move($6)); + } TOK_SEMICOL simple_behavioral_stmt TOK_RPAREN gen_stmt_block { SET_AST_NODE_LOC(ast_stack.back(), @1, @11); rewriteGenForDeclInit(ast_stack.back()); ast_stack.pop_back(); } | - TOK_IF '(' expr ')' { - AstNode *node = new AstNode(AST_GENIF); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); - ast_stack.back()->children.push_back($3); + TOK_IF TOK_LPAREN expr TOK_RPAREN { + (void)pushChild(std::make_unique(AST_GENIF)); + ast_stack.back()->children.push_back(std::move($3)); } gen_stmt_block opt_gen_else { SET_AST_NODE_LOC(ast_stack.back(), @1, @7); ast_stack.pop_back(); } | - case_type '(' expr ')' { - AstNode *node = new AstNode(AST_GENCASE, $3); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); + case_type TOK_LPAREN expr TOK_RPAREN { + (void)pushChild(std::make_unique(AST_GENCASE, std::move($3))); } gen_case_body TOK_ENDCASE { case_type_stack.pop_back(); SET_AST_NODE_LOC(ast_stack.back(), @1, @7); ast_stack.pop_back(); } | TOK_MSG_TASKS { - AstNode *node = new AstNode(AST_TECALL); + AstNode* node = pushChild(std::make_unique(AST_TECALL)); node->str = *$1; - delete $1; - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); - } opt_arg_list ';'{ + } opt_arg_list TOK_SEMICOL{ SET_AST_NODE_LOC(ast_stack.back(), @1, @3); ast_stack.pop_back(); }; @@ -3174,15 +3056,11 @@ gen_block: TOK_BEGIN { enterTypeScope(); } opt_label { - AstNode *node = new AstNode(AST_GENBLOCK); + AstNode* node = pushChild(std::make_unique(AST_GENBLOCK)); node->str = $3 ? *$3 : std::string(); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); } module_gen_body TOK_END opt_label { exitTypeScope(); checkLabelsMatch("Begin label", $3, $7); - delete $3; - delete $7; SET_AST_NODE_LOC(ast_stack.back(), @1, @7); ast_stack.pop_back(); }; @@ -3190,9 +3068,7 @@ gen_block: // result is wrapped in a genblock only if necessary gen_stmt_block: { - AstNode *node = new AstNode(AST_GENBLOCK); - ast_stack.back()->children.push_back(node); - ast_stack.push_back(node); + (void)pushChild(std::make_unique(AST_GENBLOCK)); } gen_stmt_or_module_body_stmt { SET_AST_NODE_LOC(ast_stack.back(), @2, @2); ast_stack.pop_back(); @@ -3203,336 +3079,327 @@ opt_gen_else: expr: basic_expr { - $$ = $1; + $$ = std::move($1); } | - basic_expr '?' attr expr ':' expr { - $$ = new AstNode(AST_TERNARY); - $$->children.push_back($1); - $$->children.push_back($4); - $$->children.push_back($6); - SET_AST_NODE_LOC($$, @1, @$); - append_attr($$, $3); + basic_expr TOK_QUE attr expr TOK_COL expr { + $$ = std::make_unique(AST_TERNARY); + $$->children.push_back(std::move($1)); + $$->children.push_back(std::move($4)); + $$->children.push_back(std::move($6)); + SET_AST_NODE_LOC($$.get(), @1, @$); + append_attr($$.get(), $3); } | inc_or_dec_op attr rvalue { - $$ = addIncOrDecExpr($3, $2, $1, @1, @3, false); + $$ = addIncOrDecExpr(std::move($3), $2, $1, @1, @3, false); } | // TODO: Attributes are allowed in the middle here, but they create some // non-trivial conflicts that don't seem worth solving for now. rvalue inc_or_dec_op { - $$ = addIncOrDecExpr($1, nullptr, $2, @1, @2, true); + $$ = addIncOrDecExpr(std::move($1), nullptr, $2, @1, @2, true); }; basic_expr: rvalue { - $$ = $1; + $$ = std::move($1); } | - '(' expr ')' integral_number { + TOK_LPAREN expr TOK_RPAREN integral_number { if ($4->compare(0, 1, "'") != 0) frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. () , while %s is not a sized constant.", $4->c_str()); - AstNode *bits = $2; - AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); - if (val == NULL) + auto val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); + if (val == nullptr) log_error("Value conversion failed: `%s'\n", $4->c_str()); - $$ = new AstNode(AST_TO_BITS, bits, val); - delete $4; + $$ = std::make_unique(AST_TO_BITS, std::move($2), std::move(val)); } | hierarchical_id integral_number { if ($2->compare(0, 1, "'") != 0) frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. \'d0, while %s is not a sized constant.", $2->c_str()); - AstNode *bits = new AstNode(AST_IDENTIFIER); + auto bits = std::make_unique(AST_IDENTIFIER); bits->str = *$1; - SET_AST_NODE_LOC(bits, @1, @1); - AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); - SET_AST_NODE_LOC(val, @2, @2); - if (val == NULL) + SET_AST_NODE_LOC(bits.get(), @1, @1); + auto val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); + SET_AST_NODE_LOC(val.get(), @2, @2); + if (val == nullptr) log_error("Value conversion failed: `%s'\n", $2->c_str()); - $$ = new AstNode(AST_TO_BITS, bits, val); - delete $1; - delete $2; + $$ = std::make_unique(AST_TO_BITS, std::move(bits), std::move(val)); } | integral_number { $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); - SET_AST_NODE_LOC($$, @1, @1); - if ($$ == NULL) + SET_AST_NODE_LOC($$.get(), @1, @1); + if ($$ == nullptr) log_error("Value conversion failed: `%s'\n", $1->c_str()); - delete $1; } | TOK_REALVAL { - $$ = new AstNode(AST_REALVALUE); + $$ = std::make_unique(AST_REALVALUE); char *p = (char*)malloc(GetSize(*$1) + 1), *q; for (int i = 0, j = 0; j < GetSize(*$1); j++) if ((*$1)[j] != '_') p[i++] = (*$1)[j], p[i] = 0; $$->realvalue = strtod(p, &q); - SET_AST_NODE_LOC($$, @1, @1); + SET_AST_NODE_LOC($$.get(), @1, @1); log_assert(*q == 0); - delete $1; free(p); } | TOK_STRING { $$ = AstNode::mkconst_str(*$1); - SET_AST_NODE_LOC($$, @1, @1); - delete $1; + SET_AST_NODE_LOC($$.get(), @1, @1); } | hierarchical_id attr { + // super sketchy! Orphaned pointer in non-owning ast_stack AstNode *node = new AstNode(AST_FCALL); node->str = *$1; - delete $1; ast_stack.push_back(node); SET_AST_NODE_LOC(node, @1, @1); append_attr(node, $2); - } '(' arg_list optional_comma ')' { - $$ = ast_stack.back(); + } TOK_LPAREN arg_list optional_comma TOK_RPAREN { + $$.reset(ast_stack.back()); ast_stack.pop_back(); } | - TOK_TO_SIGNED attr '(' expr ')' { - $$ = new AstNode(AST_TO_SIGNED, $4); - append_attr($$, $2); + TOK_TO_SIGNED attr TOK_LPAREN expr TOK_RPAREN { + $$ = std::make_unique(AST_TO_SIGNED, std::move($4)); + append_attr($$.get(), $2); } | - TOK_TO_UNSIGNED attr '(' expr ')' { - $$ = new AstNode(AST_TO_UNSIGNED, $4); - append_attr($$, $2); + TOK_TO_UNSIGNED attr TOK_LPAREN expr TOK_RPAREN { + $$ = std::make_unique(AST_TO_UNSIGNED, std::move($4)); + append_attr($$.get(), $2); } | - '(' expr ')' { - $$ = $2; + TOK_LPAREN expr TOK_RPAREN { + $$ = std::move($2); } | - '(' expr ':' expr ':' expr ')' { - delete $2; - $$ = $4; - delete $6; + TOK_LPAREN expr TOK_COL expr TOK_COL expr TOK_RPAREN { + $$ = std::move($4); } | - '{' concat_list '}' { - $$ = $2; + TOK_LCURL concat_list TOK_RCURL { + $$ = std::move($2); } | - '{' expr '{' concat_list '}' '}' { - $$ = new AstNode(AST_REPLICATE, $2, $4); + TOK_LCURL expr TOK_LCURL concat_list TOK_RCURL TOK_RCURL { + $$ = std::make_unique(AST_REPLICATE, std::move($2), std::move($4)); } | - '~' attr basic_expr %prec UNARY_OPS { - $$ = new AstNode(AST_BIT_NOT, $3); - SET_AST_NODE_LOC($$, @1, @3); - append_attr($$, $2); + TOK_TILDE attr basic_expr %prec UNARY_OPS { + $$ = std::make_unique(AST_BIT_NOT, std::move($3)); + SET_AST_NODE_LOC($$.get(), @1, @3); + append_attr($$.get(), $2); } | - basic_expr '&' attr basic_expr { - $$ = new AstNode(AST_BIT_AND, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + basic_expr TOK_AMP attr basic_expr { + $$ = std::make_unique(AST_BIT_AND, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_NAND attr basic_expr { - $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_AND, $1, $4)); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_BIT_NOT, std::make_unique(AST_BIT_AND, std::move($1), std::move($4))); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - basic_expr '|' attr basic_expr { - $$ = new AstNode(AST_BIT_OR, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + basic_expr TOK_PIPE attr basic_expr { + $$ = std::make_unique(AST_BIT_OR, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_NOR attr basic_expr { - $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_OR, $1, $4)); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_BIT_NOT, std::make_unique(AST_BIT_OR, std::move($1), std::move($4))); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - basic_expr '^' attr basic_expr { - $$ = new AstNode(AST_BIT_XOR, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + basic_expr TOK_CARET attr basic_expr { + $$ = std::make_unique(AST_BIT_XOR, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_XNOR attr basic_expr { - $$ = new AstNode(AST_BIT_XNOR, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_BIT_XNOR, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - '&' attr basic_expr %prec UNARY_OPS { - $$ = new AstNode(AST_REDUCE_AND, $3); - SET_AST_NODE_LOC($$, @1, @3); - append_attr($$, $2); + TOK_AMP attr basic_expr %prec UNARY_OPS { + $$ = std::make_unique(AST_REDUCE_AND, std::move($3)); + SET_AST_NODE_LOC($$.get(), @1, @3); + append_attr($$.get(), $2); } | OP_NAND attr basic_expr %prec UNARY_OPS { - $$ = new AstNode(AST_REDUCE_AND, $3); - SET_AST_NODE_LOC($$, @1, @3); - append_attr($$, $2); - $$ = new AstNode(AST_LOGIC_NOT, $$); + $$ = std::make_unique(AST_REDUCE_AND, std::move($3)); + SET_AST_NODE_LOC($$.get(), @1, @3); + append_attr($$.get(), $2); + $$ = std::make_unique(AST_LOGIC_NOT, std::move($$)); } | - '|' attr basic_expr %prec UNARY_OPS { - $$ = new AstNode(AST_REDUCE_OR, $3); - SET_AST_NODE_LOC($$, @1, @3); - append_attr($$, $2); + TOK_PIPE attr basic_expr %prec UNARY_OPS { + $$ = std::make_unique(AST_REDUCE_OR, std::move($3)); + SET_AST_NODE_LOC($$.get(), @1, @3); + append_attr($$.get(), std::move($2)); } | OP_NOR attr basic_expr %prec UNARY_OPS { - $$ = new AstNode(AST_REDUCE_OR, $3); - SET_AST_NODE_LOC($$, @1, @3); - append_attr($$, $2); - $$ = new AstNode(AST_LOGIC_NOT, $$); - SET_AST_NODE_LOC($$, @1, @3); + $$ = std::make_unique(AST_REDUCE_OR, std::move($3)); + SET_AST_NODE_LOC($$.get(), @1, @3); + append_attr($$.get(), $2); + $$ = std::make_unique(AST_LOGIC_NOT, std::move($$)); + SET_AST_NODE_LOC($$.get(), @1, @3); } | - '^' attr basic_expr %prec UNARY_OPS { - $$ = new AstNode(AST_REDUCE_XOR, $3); - SET_AST_NODE_LOC($$, @1, @3); - append_attr($$, $2); + TOK_CARET attr basic_expr %prec UNARY_OPS { + $$ = std::make_unique(AST_REDUCE_XOR, std::move($3)); + SET_AST_NODE_LOC($$.get(), @1, @3); + append_attr($$.get(), $2); } | OP_XNOR attr basic_expr %prec UNARY_OPS { - $$ = new AstNode(AST_REDUCE_XNOR, $3); - SET_AST_NODE_LOC($$, @1, @3); - append_attr($$, $2); + $$ = std::make_unique(AST_REDUCE_XNOR, std::move($3)); + SET_AST_NODE_LOC($$.get(), @1, @3); + append_attr($$.get(), $2); } | basic_expr OP_SHL attr basic_expr { - $$ = new AstNode(AST_SHIFT_LEFT, $1, new AstNode(AST_TO_UNSIGNED, $4)); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_SHIFT_LEFT, std::move($1), std::make_unique(AST_TO_UNSIGNED, std::move($4))); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_SHR attr basic_expr { - $$ = new AstNode(AST_SHIFT_RIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4)); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_SHIFT_RIGHT, std::move($1), std::make_unique(AST_TO_UNSIGNED, std::move($4))); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_SSHL attr basic_expr { - $$ = new AstNode(AST_SHIFT_SLEFT, $1, new AstNode(AST_TO_UNSIGNED, $4)); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_SHIFT_SLEFT, std::move($1), std::make_unique(AST_TO_UNSIGNED, std::move($4))); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_SSHR attr basic_expr { - $$ = new AstNode(AST_SHIFT_SRIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4)); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_SHIFT_SRIGHT, std::move($1), std::make_unique(AST_TO_UNSIGNED, std::move($4))); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - basic_expr '<' attr basic_expr { - $$ = new AstNode(AST_LT, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + basic_expr TOK_LT attr basic_expr { + $$ = std::make_unique(AST_LT, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_LE attr basic_expr { - $$ = new AstNode(AST_LE, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_LE, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_EQ attr basic_expr { - $$ = new AstNode(AST_EQ, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_EQ, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_NE attr basic_expr { - $$ = new AstNode(AST_NE, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_NE, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_EQX attr basic_expr { - $$ = new AstNode(AST_EQX, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_EQX, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_NEX attr basic_expr { - $$ = new AstNode(AST_NEX, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_NEX, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_GE attr basic_expr { - $$ = new AstNode(AST_GE, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_GE, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - basic_expr '>' attr basic_expr { - $$ = new AstNode(AST_GT, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + basic_expr TOK_GT attr basic_expr { + $$ = std::make_unique(AST_GT, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - basic_expr '+' attr basic_expr { - $$ = new AstNode(AST_ADD, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + basic_expr TOK_PLUS attr basic_expr { + $$ = std::make_unique(AST_ADD, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - basic_expr '-' attr basic_expr { - $$ = new AstNode(AST_SUB, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + basic_expr TOK_MINUS attr basic_expr { + $$ = std::make_unique(AST_SUB, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - basic_expr '*' attr basic_expr { - $$ = new AstNode(AST_MUL, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + basic_expr TOK_ASTER attr basic_expr { + $$ = std::make_unique(AST_MUL, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - basic_expr '/' attr basic_expr { - $$ = new AstNode(AST_DIV, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + basic_expr TOK_SLASH attr basic_expr { + $$ = std::make_unique(AST_DIV, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - basic_expr '%' attr basic_expr { - $$ = new AstNode(AST_MOD, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + basic_expr TOK_PERC attr basic_expr { + $$ = std::make_unique(AST_MOD, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_POW attr basic_expr { - $$ = new AstNode(AST_POW, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_POW, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - '+' attr basic_expr %prec UNARY_OPS { - $$ = new AstNode(AST_POS, $3); - SET_AST_NODE_LOC($$, @1, @3); - append_attr($$, $2); + TOK_PLUS attr basic_expr %prec UNARY_OPS { + $$ = std::make_unique(AST_POS, std::move($3)); + SET_AST_NODE_LOC($$.get(), @1, @3); + append_attr($$.get(), $2); } | - '-' attr basic_expr %prec UNARY_OPS { - $$ = new AstNode(AST_NEG, $3); - SET_AST_NODE_LOC($$, @1, @3); - append_attr($$, $2); + TOK_MINUS attr basic_expr %prec UNARY_OPS { + $$ = std::make_unique(AST_NEG, std::move($3)); + SET_AST_NODE_LOC($$.get(), @1, @3); + append_attr($$.get(), $2); } | basic_expr OP_LAND attr basic_expr { - $$ = new AstNode(AST_LOGIC_AND, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_LOGIC_AND, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | basic_expr OP_LOR attr basic_expr { - $$ = new AstNode(AST_LOGIC_OR, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); - append_attr($$, $3); + $$ = std::make_unique(AST_LOGIC_OR, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); } | - '!' attr basic_expr %prec UNARY_OPS { - $$ = new AstNode(AST_LOGIC_NOT, $3); - SET_AST_NODE_LOC($$, @1, @3); - append_attr($$, $2); + TOK_EXCL attr basic_expr %prec UNARY_OPS { + $$ = std::make_unique(AST_LOGIC_NOT, std::move($3)); + SET_AST_NODE_LOC($$.get(), @1, @3); + append_attr($$.get(), $2); } | - TOK_SIGNED OP_CAST '(' expr ')' { + TOK_SIGNED OP_CAST TOK_LPAREN expr TOK_RPAREN { if (!sv_mode) frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode."); - $$ = new AstNode(AST_TO_SIGNED, $4); - SET_AST_NODE_LOC($$, @1, @4); + $$ = std::make_unique(AST_TO_SIGNED, std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); } | - TOK_UNSIGNED OP_CAST '(' expr ')' { + TOK_UNSIGNED OP_CAST TOK_LPAREN expr TOK_RPAREN { if (!sv_mode) frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode."); - $$ = new AstNode(AST_TO_UNSIGNED, $4); - SET_AST_NODE_LOC($$, @1, @4); + $$ = std::make_unique(AST_TO_UNSIGNED, std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); } | - basic_expr OP_CAST '(' expr ')' { + basic_expr OP_CAST TOK_LPAREN expr TOK_RPAREN { if (!sv_mode) frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode."); - $$ = new AstNode(AST_CAST_SIZE, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); + $$ = std::make_unique(AST_CAST_SIZE, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); } | - typedef_base_type OP_CAST '(' expr ')' { + typedef_base_type OP_CAST TOK_LPAREN expr TOK_RPAREN { if (!sv_mode) frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode."); - $$ = new AstNode(AST_CAST_SIZE, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); + $$ = std::make_unique(AST_CAST_SIZE, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); } | - '(' expr '=' expr ')' { + TOK_LPAREN expr TOK_EQ expr TOK_RPAREN { ensureAsgnExprAllowed(); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, $4); - ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @2, @4); $$ = $2->clone(); + auto node = std::make_unique(AST_ASSIGN_EQ, std::move($2), std::move($4)); + SET_AST_NODE_LOC(node.get(), @2, @4); + ast_stack.back()->children.push_back(std::move(node)); } | - '(' expr asgn_binop expr ')' { + TOK_LPAREN expr asgn_binop expr TOK_RPAREN { ensureAsgnExprAllowed(); - $$ = addAsgnBinopStmt(nullptr, $2, $3, $4, @2, @4)-> clone(); + $$ = addAsgnBinopStmt(nullptr, std::move($2), $3, std::move($4), @2, @4)-> clone(); }; concat_list: expr { - $$ = new AstNode(AST_CONCAT, $1); + $$ = std::make_unique(AST_CONCAT, std::move($1)); } | - expr ',' concat_list { - $$ = $3; - $$->children.push_back($1); + expr TOK_COMMA concat_list { + $$ = std::move($3); + $$->children.push_back(std::move($1)); }; integral_number: @@ -3540,12 +3407,9 @@ integral_number: TOK_UNBASED_UNSIZED_CONSTVAL { $$ = $1; } | TOK_BASE TOK_BASED_CONSTVAL { $1->append(*$2); - $$ = $1; - delete $2; + $$ = std::move($1); } | TOK_CONSTVAL TOK_BASE TOK_BASED_CONSTVAL { $1->append(*$2).append(*$3); - $$ = $1; - delete $2; - delete $3; + $$ = std::move($1); }; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index c08e78dce..23d0e0d36 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -947,10 +947,6 @@ RTLIL::Design::~Design() delete pr.second; for (auto n : bindings_) delete n; - for (auto n : verilog_packages) - delete n; - for (auto n : verilog_globals) - delete n; #ifdef WITH_PYTHON RTLIL::Design::get_all_designs()->erase(hashidx_); #endif @@ -5708,12 +5704,12 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri if (('0' <= netname[0] && netname[0] <= '9') || netname[0] == '\'') { cover("kernel.rtlil.sigspec.parse.const"); - AST::get_line_num = sigspec_parse_get_dummy_line_num; - AST::AstNode *ast = VERILOG_FRONTEND::const2ast(netname); - if (ast == NULL) + // TODO fix + // AST::get_line_num = sigspec_parse_get_dummy_line_num; + auto ast = VERILOG_FRONTEND::const2ast(netname); + if (ast == nullptr) return false; sig.append(RTLIL::Const(ast->bits)); - delete ast; continue; } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 504fa0062..ec66746e6 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1331,7 +1331,7 @@ struct RTLIL::Design dict modules_; std::vector bindings_; - std::vector verilog_packages, verilog_globals; + std::vector> verilog_packages, verilog_globals; std::unique_ptr verilog_defines; std::vector selection_stack; diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index a2ae45ef3..59cd39c98 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -368,14 +368,8 @@ struct DesignPass : public Pass { if (reset_mode || reset_vlog_mode || !load_name.empty() || push_mode || pop_mode) { - for (auto node : design->verilog_packages) - delete node; design->verilog_packages.clear(); - - for (auto node : design->verilog_globals) - delete node; design->verilog_globals.clear(); - design->verilog_defines->clear(); } diff --git a/passes/memory/memlib.h b/passes/memory/memlib.h index c3f7728f1..43dec7386 100644 --- a/passes/memory/memlib.h +++ b/passes/memory/memlib.h @@ -100,7 +100,7 @@ enum class WrTransKind { struct WrTransDef { WrTransTargetKind target_kind; - int target_group; + int target_group = 0; WrTransKind kind; }; diff --git a/tests/sat/alu.v b/tests/sat/alu.v index 9826fe05d..76945dc65 100644 --- a/tests/sat/alu.v +++ b/tests/sat/alu.v @@ -1,4 +1,4 @@ -module alu( +module alu ( input clk, input [7:0] A, input [7:0] B, diff --git a/tests/various/svalways.sh b/tests/various/svalways.sh index 7765907c7..4d3e334ed 100755 --- a/tests/various/svalways.sh +++ b/tests/various/svalways.sh @@ -27,7 +27,7 @@ always_comb @(d) endmodule EOT -) 2>&1 | grep -F ":3: ERROR: syntax error, unexpected '@'" > /dev/null +) 2>&1 | grep -F "ERROR: syntax error, unexpected @" > /dev/null # Incorrect use of always_comb ((../../yosys -f "verilog -sv" -qp proc -|| true) <