verilog_parser: Properly handle recursion when processing attributes

Fixes #737

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
Sylvain Munaut 2018-12-13 18:47:05 +01:00
parent 0b9bb852c6
commit 58fb2ac818
1 changed files with 29 additions and 19 deletions

View File

@ -35,6 +35,7 @@
%{ %{
#include <list> #include <list>
#include <stack>
#include <string.h> #include <string.h>
#include "frontends/verilog/verilog_frontend.h" #include "frontends/verilog/verilog_frontend.h"
#include "kernel/log.h" #include "kernel/log.h"
@ -47,7 +48,8 @@ YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND { namespace VERILOG_FRONTEND {
int port_counter; int port_counter;
std::map<std::string, int> port_stubs; std::map<std::string, int> port_stubs;
std::map<std::string, AstNode*> attr_list, default_attr_list; std::map<std::string, AstNode*> *attr_list, default_attr_list;
std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
std::map<std::string, AstNode*> *albuf; std::map<std::string, AstNode*> *albuf;
std::vector<AstNode*> ast_stack; std::vector<AstNode*> ast_stack;
struct AstNode *astbuf1, *astbuf2, *astbuf3; struct AstNode *astbuf1, *astbuf2, *astbuf3;
@ -175,15 +177,18 @@ design:
attr: attr:
{ {
for (auto &it : attr_list) if (attr_list != nullptr)
delete it.second; attr_list_stack.push(attr_list);
attr_list.clear(); attr_list = new std::map<std::string, AstNode*>;
for (auto &it : default_attr_list) for (auto &it : default_attr_list)
attr_list[it.first] = it.second->clone(); (*attr_list)[it.first] = it.second->clone();
} attr_opt { } attr_opt {
std::map<std::string, AstNode*> *al = new std::map<std::string, AstNode*>; $$ = attr_list;
al->swap(attr_list); if (!attr_list_stack.empty()) {
$$ = al; attr_list = attr_list_stack.top();
attr_list_stack.pop();
} else
attr_list = nullptr;
}; };
attr_opt: attr_opt:
@ -192,15 +197,20 @@ attr_opt:
defattr: defattr:
DEFATTR_BEGIN { DEFATTR_BEGIN {
if (attr_list != nullptr)
attr_list_stack.push(attr_list);
attr_list = new std::map<std::string, AstNode*>;
for (auto &it : default_attr_list) for (auto &it : default_attr_list)
delete it.second; delete it.second;
default_attr_list.clear(); default_attr_list.clear();
for (auto &it : attr_list)
delete it.second;
attr_list.clear();
} opt_attr_list { } opt_attr_list {
default_attr_list = attr_list; attr_list->swap(default_attr_list);
attr_list.clear(); delete attr_list;
if (!attr_list_stack.empty()) {
attr_list = attr_list_stack.top();
attr_list_stack.pop();
} else
attr_list = nullptr;
} DEFATTR_END; } DEFATTR_END;
opt_attr_list: opt_attr_list:
@ -212,15 +222,15 @@ attr_list:
attr_assign: attr_assign:
hierarchical_id { hierarchical_id {
if (attr_list.count(*$1) != 0) if (attr_list->count(*$1) != 0)
delete attr_list[*$1]; delete (*attr_list)[*$1];
attr_list[*$1] = AstNode::mkconst_int(1, false); (*attr_list)[*$1] = AstNode::mkconst_int(1, false);
delete $1; delete $1;
} | } |
hierarchical_id '=' expr { hierarchical_id '=' expr {
if (attr_list.count(*$1) != 0) if (attr_list->count(*$1) != 0)
delete attr_list[*$1]; delete (*attr_list)[*$1];
attr_list[*$1] = $3; (*attr_list)[*$1] = $3;
delete $1; delete $1;
}; };