Add check for explicit lifetime when initialising static variables.
If a static variable declared in a task, function, or block has an
initialisation expression, SystemVerilog requires the declaration to
have an explicit static lifetime. This is supposed to be a compile
error, but for now just output a warning.
Implementing this required adding support in the parser for explicit
lifetimes in variable declarations. For now, just output an error if
the user asks for a lifetime that isn't the default for that scope.
(cherry picked from commit 9538c81d34)
This commit is contained in:
parent
7d2eeb0137
commit
5bbb054173
|
|
@ -19,6 +19,11 @@
|
||||||
|
|
||||||
# include "PScope.h"
|
# include "PScope.h"
|
||||||
|
|
||||||
|
bool LexicalScope::var_init_needs_explicit_lifetime() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
PScope::PScope(perm_string n, LexicalScope*parent)
|
PScope::PScope(perm_string n, LexicalScope*parent)
|
||||||
: LexicalScope(parent), name_(n)
|
: LexicalScope(parent), name_(n)
|
||||||
{
|
{
|
||||||
|
|
@ -58,4 +63,3 @@ PScopeExtra::PScopeExtra(perm_string n)
|
||||||
PScopeExtra::~PScopeExtra()
|
PScopeExtra::~PScopeExtra()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
7
PScope.h
7
PScope.h
|
|
@ -53,11 +53,12 @@ class NetScope;
|
||||||
class LexicalScope {
|
class LexicalScope {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LexicalScope(LexicalScope*parent) : parent_(parent) { }
|
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
|
||||||
|
|
||||||
|
explicit LexicalScope(LexicalScope*parent) : default_lifetime(INHERITED), parent_(parent) { }
|
||||||
// A virtual destructor is so that dynamic_cast can work.
|
// A virtual destructor is so that dynamic_cast can work.
|
||||||
virtual ~LexicalScope() { }
|
virtual ~LexicalScope() { }
|
||||||
|
|
||||||
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
|
|
||||||
lifetime_t default_lifetime;
|
lifetime_t default_lifetime;
|
||||||
|
|
||||||
struct range_t {
|
struct range_t {
|
||||||
|
|
@ -124,6 +125,8 @@ class LexicalScope {
|
||||||
|
|
||||||
LexicalScope* parent_scope() const { return parent_; }
|
LexicalScope* parent_scope() const { return parent_; }
|
||||||
|
|
||||||
|
virtual bool var_init_needs_explicit_lifetime() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void dump_typedefs_(ostream&out, unsigned indent) const;
|
void dump_typedefs_(ostream&out, unsigned indent) const;
|
||||||
|
|
||||||
|
|
|
||||||
5
PTask.cc
5
PTask.cc
|
|
@ -30,6 +30,11 @@ PTaskFunc::~PTaskFunc()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PTaskFunc::var_init_needs_explicit_lifetime() const
|
||||||
|
{
|
||||||
|
return default_lifetime == STATIC;
|
||||||
|
}
|
||||||
|
|
||||||
void PTaskFunc::set_ports(vector<pform_tf_port_t>*p)
|
void PTaskFunc::set_ports(vector<pform_tf_port_t>*p)
|
||||||
{
|
{
|
||||||
assert(ports_ == 0);
|
assert(ports_ == 0);
|
||||||
|
|
|
||||||
2
PTask.h
2
PTask.h
|
|
@ -41,6 +41,8 @@ class PTaskFunc : public PScope, public LineInfo {
|
||||||
PTaskFunc(perm_string name, LexicalScope*parent);
|
PTaskFunc(perm_string name, LexicalScope*parent);
|
||||||
~PTaskFunc();
|
~PTaskFunc();
|
||||||
|
|
||||||
|
bool var_init_needs_explicit_lifetime() const;
|
||||||
|
|
||||||
void set_ports(std::vector<pform_tf_port_t>*p);
|
void set_ports(std::vector<pform_tf_port_t>*p);
|
||||||
|
|
||||||
void set_this(class_type_t*use_type, PWire*this_wire);
|
void set_this(class_type_t*use_type, PWire*this_wire);
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,11 @@ PBlock::~PBlock()
|
||||||
delete list_[idx];
|
delete list_[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PBlock::var_init_needs_explicit_lifetime() const
|
||||||
|
{
|
||||||
|
return default_lifetime == STATIC;
|
||||||
|
}
|
||||||
|
|
||||||
PChainConstructor* PBlock::extract_chain_constructor()
|
PChainConstructor* PBlock::extract_chain_constructor()
|
||||||
{
|
{
|
||||||
if (list_.empty())
|
if (list_.empty())
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,8 @@ class PBlock : public PScope, public Statement {
|
||||||
|
|
||||||
BL_TYPE bl_type() const { return bl_type_; }
|
BL_TYPE bl_type() const { return bl_type_; }
|
||||||
|
|
||||||
|
bool var_init_needs_explicit_lifetime() const;
|
||||||
|
|
||||||
// This is only used if this block is the statement list for a
|
// This is only used if this block is the statement list for a
|
||||||
// constructor. We look for a PChainConstructor as the first
|
// constructor. We look for a PChainConstructor as the first
|
||||||
// statement, and if it is there, extract it.
|
// statement, and if it is there, extract it.
|
||||||
|
|
|
||||||
43
parse.y
43
parse.y
|
|
@ -65,6 +65,10 @@ static PTask* current_task = 0;
|
||||||
static PFunction* current_function = 0;
|
static PFunction* current_function = 0;
|
||||||
static stack<PBlock*> current_block_stack;
|
static stack<PBlock*> current_block_stack;
|
||||||
|
|
||||||
|
/* The variable declaration rules need to know if a lifetime has been
|
||||||
|
specified. */
|
||||||
|
static LexicalScope::lifetime_t var_lifetime;
|
||||||
|
|
||||||
static pform_name_t* pform_create_this(void)
|
static pform_name_t* pform_create_this(void)
|
||||||
{
|
{
|
||||||
name_component_t name (perm_string::literal("@"));
|
name_component_t name (perm_string::literal("@"));
|
||||||
|
|
@ -667,7 +671,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
%type <int_val> atom2_type
|
%type <int_val> atom2_type
|
||||||
%type <int_val> module_start module_end
|
%type <int_val> module_start module_end
|
||||||
|
|
||||||
%type <lifetime> lifetime_opt
|
%type <lifetime> lifetime lifetime_opt
|
||||||
|
|
||||||
%token K_TAND
|
%token K_TAND
|
||||||
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
||||||
|
|
@ -1369,9 +1373,13 @@ jump_statement /* IEEE1800-2005: A.6.5 */
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
lifetime_opt /* IEEE1800-2005: A.2.1.3 */
|
lifetime /* IEEE1800-2005: A.2.1.3 */
|
||||||
: K_automatic { $$ = LexicalScope::AUTOMATIC; }
|
: K_automatic { $$ = LexicalScope::AUTOMATIC; }
|
||||||
| K_static { $$ = LexicalScope::STATIC; }
|
| K_static { $$ = LexicalScope::STATIC; }
|
||||||
|
;
|
||||||
|
|
||||||
|
lifetime_opt /* IEEE1800-2005: A.2.1.3 */
|
||||||
|
: lifetime { $$ = $1; }
|
||||||
| { $$ = LexicalScope::INHERITED; }
|
| { $$ = LexicalScope::INHERITED; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -2254,6 +2262,19 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
variable_lifetime
|
||||||
|
: lifetime
|
||||||
|
{ if (!gn_system_verilog()) {
|
||||||
|
yyerror(@1, "error: overriding the default variable lifetime "
|
||||||
|
"requires SystemVerilog.");
|
||||||
|
} else if ($1 != pform_peek_scope()->default_lifetime) {
|
||||||
|
yyerror(@1, "sorry: overriding the default variable lifetime "
|
||||||
|
"is not yet supported.");
|
||||||
|
}
|
||||||
|
var_lifetime = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
/* Verilog-2001 supports attribute lists, which can be attached to a
|
/* Verilog-2001 supports attribute lists, which can be attached to a
|
||||||
variety of different objects. The syntax inside the (* *) is a
|
variety of different objects. The syntax inside the (* *) is a
|
||||||
comma separated list of names or names with assigned values. */
|
comma separated list of names or names with assigned values. */
|
||||||
|
|
@ -2328,10 +2349,20 @@ block_item_decl
|
||||||
{ if ($1) pform_set_data_type(@1, $1, $2, NetNet::REG, attributes_in_context);
|
{ if ($1) pform_set_data_type(@1, $1, $2, NetNet::REG, attributes_in_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| variable_lifetime data_type register_variable_list ';'
|
||||||
|
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
|
||||||
|
var_lifetime = LexicalScope::INHERITED;
|
||||||
|
}
|
||||||
|
|
||||||
| K_reg data_type register_variable_list ';'
|
| K_reg data_type register_variable_list ';'
|
||||||
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
|
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| variable_lifetime K_reg data_type register_variable_list ';'
|
||||||
|
{ if ($3) pform_set_data_type(@3, $3, $4, NetNet::REG, attributes_in_context);
|
||||||
|
var_lifetime = LexicalScope::INHERITED;
|
||||||
|
}
|
||||||
|
|
||||||
| K_event event_variable_list ';'
|
| K_event event_variable_list ';'
|
||||||
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
|
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
|
||||||
}
|
}
|
||||||
|
|
@ -5492,7 +5523,13 @@ register_variable
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
| IDENTIFIER dimensions_opt '=' expression
|
| IDENTIFIER dimensions_opt '=' expression
|
||||||
{ perm_string name = lex_strings.make($1);
|
{ if (pform_peek_scope()->var_init_needs_explicit_lifetime()
|
||||||
|
&& (var_lifetime == LexicalScope::INHERITED)) {
|
||||||
|
cerr << @3 << ": warning: Static variable initialization requires "
|
||||||
|
"explicit lifetime in this context." << endl;
|
||||||
|
warn_count += 1;
|
||||||
|
}
|
||||||
|
perm_string name = lex_strings.make($1);
|
||||||
pform_makewire(@1, name, NetNet::REG,
|
pform_makewire(@1, name, NetNet::REG,
|
||||||
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
||||||
pform_set_reg_idx(name, $2);
|
pform_set_reg_idx(name, $2);
|
||||||
|
|
|
||||||
1
pform.cc
1
pform.cc
|
|
@ -513,6 +513,7 @@ PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
|
||||||
}
|
}
|
||||||
|
|
||||||
PBlock*block = new PBlock(block_name, lexical_scope, bt);
|
PBlock*block = new PBlock(block_name, lexical_scope, bt);
|
||||||
|
block->default_lifetime = find_lifetime(LexicalScope::INHERITED);
|
||||||
lexical_scope = block;
|
lexical_scope = block;
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue