Add support for void cast function call
SystemVerilog has explicit support for calling a function as a statement. This is allowed when the function call is encapsulated in `void'(...)`. E.g. `void'(f(1, 2, 3));` We already support calling function calls as statements without the void cast and emit a warning when doing so. Adding support for void casts only requires to update the parser to handle the void cast and then do not emit the warning if a function is called as a statement as part of a void cast. Void casting a task or void function call is not allowed and will generate an elaboration error. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
54956f0f29
commit
0e62ff153d
|
|
@ -226,6 +226,8 @@ class PCallTask : public Statement {
|
|||
|
||||
bool elaborate_elab(Design*des, NetScope*scope) const;
|
||||
|
||||
void void_cast() { void_cast_ = true; }
|
||||
|
||||
private:
|
||||
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
||||
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
||||
|
|
@ -257,6 +259,7 @@ class PCallTask : public Statement {
|
|||
PPackage*package_;
|
||||
pform_name_t path_;
|
||||
std::vector<PExpr*> parms_;
|
||||
bool void_cast_ = false;
|
||||
};
|
||||
|
||||
class PCase : public Statement {
|
||||
|
|
|
|||
25
elaborate.cc
25
elaborate.cc
|
|
@ -3390,10 +3390,14 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
NetProc* PCallTask::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (peek_tail_name(path_)[0] == '$')
|
||||
return elaborate_sys(des, scope);
|
||||
if (peek_tail_name(path_)[0] == '$') {
|
||||
if (void_cast_)
|
||||
return elaborate_non_void_function_(des, scope);
|
||||
else
|
||||
return elaborate_sys(des, scope);
|
||||
} else {
|
||||
return elaborate_usr(des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3690,8 +3694,10 @@ NetProc* PCallTask::elaborate_method_func_(NetScope*scope,
|
|||
perm_string method_name,
|
||||
const char*sys_task_name) const
|
||||
{
|
||||
if (!void_cast_) {
|
||||
cerr << get_fileline() << ": warning: method function '"
|
||||
<< method_name << "' is being called as a task." << endl;
|
||||
}
|
||||
|
||||
// Generate the function.
|
||||
NetESFunc*sys_expr = new NetESFunc(sys_task_name, type, 1);
|
||||
|
|
@ -3906,8 +3912,11 @@ NetProc *PCallTask::elaborate_non_void_function_(Design *des, NetScope *scope) c
|
|||
PAssign*tmp = new PAssign(0, rval);
|
||||
tmp->set_file(get_file());
|
||||
tmp->set_lineno(get_lineno());
|
||||
if (!void_cast_) {
|
||||
cerr << get_fileline() << ": warning: User function '"
|
||||
<< peek_tail_name(path_) << "' is being called as a task." << endl;
|
||||
}
|
||||
|
||||
// Elaborate the assignment to a dummy variable.
|
||||
return tmp->elaborate(des, scope);
|
||||
}
|
||||
|
|
@ -3962,11 +3971,23 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
|||
// that we can catch more errors.
|
||||
test_task_calls_ok_(des, scope);
|
||||
|
||||
if (void_cast_) {
|
||||
cerr << get_fileline() << ": error: void casting user task '"
|
||||
<< peek_tail_name(path_) << "' is not allowed." << endl;
|
||||
des->errors++;
|
||||
}
|
||||
|
||||
} else if (task->type() == NetScope::FUNC) {
|
||||
NetFuncDef*tmp = task->func_def();
|
||||
if (!tmp->is_void())
|
||||
return elaborate_non_void_function_(des, scope);
|
||||
def = tmp;
|
||||
|
||||
if (void_cast_) {
|
||||
cerr << get_fileline() << ": error: void casting user void function '"
|
||||
<< peek_tail_name(path_) << "' is not allowed." << endl;
|
||||
des->errors++;
|
||||
}
|
||||
}
|
||||
|
||||
/* The caller has checked the parms_ size to make sure it
|
||||
|
|
|
|||
65
parse.y
65
parse.y
|
|
@ -420,6 +420,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
|
|||
PWire*wire;
|
||||
std::vector<PWire*>*wires;
|
||||
|
||||
PCallTask *subroutine_call;
|
||||
|
||||
PEventStatement*event_statement;
|
||||
Statement*statement;
|
||||
std::vector<Statement*>*statement_list;
|
||||
|
|
@ -685,6 +687,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
|
|||
|
||||
%type <statement> analog_statement
|
||||
|
||||
%type <subroutine_call> subroutine_call
|
||||
|
||||
%type <join_keyword> join_keyword
|
||||
|
||||
%type <letter> spec_polarity
|
||||
|
|
@ -6241,6 +6245,35 @@ spec_notifier
|
|||
{ args_after_notifier = 0; delete[]$1; }
|
||||
;
|
||||
|
||||
subroutine_call
|
||||
: hierarchy_identifier argument_list_parens_opt
|
||||
{ PCallTask*tmp = pform_make_call_task(@1, *$1, *$2);
|
||||
delete $1;
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| class_hierarchy_identifier argument_list_parens_opt
|
||||
{ PCallTask*tmp = new PCallTask(*$1, *$2);
|
||||
FILE_NAME(tmp, @1);
|
||||
delete $1;
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| SYSTEM_IDENTIFIER argument_list_parens_opt
|
||||
{ PCallTask*tmp = new PCallTask(lex_strings.make($1), *$2);
|
||||
FILE_NAME(tmp,@1);
|
||||
delete[]$1;
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| hierarchy_identifier '(' error ')'
|
||||
{ yyerror(@3, "error: Syntax error in task arguments.");
|
||||
list<PExpr*>pt;
|
||||
PCallTask*tmp = pform_make_call_task(@1, *$1, pt);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
statement_item /* This is roughly statement_item in the LRM */
|
||||
|
||||
|
|
@ -6592,19 +6625,13 @@ statement_item /* This is roughly statement_item in the LRM */
|
|||
FILE_NAME(tmp,@1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| SYSTEM_IDENTIFIER argument_list_parens_opt ';'
|
||||
{ PCallTask*tmp = new PCallTask(lex_strings.make($1), *$2);
|
||||
FILE_NAME(tmp,@1);
|
||||
delete[]$1;
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
| K_void '\'' '(' subroutine_call ')' ';'
|
||||
{ $4->void_cast();
|
||||
$$ = $4;
|
||||
}
|
||||
|
||||
| hierarchy_identifier argument_list_parens_opt ';'
|
||||
{ PCallTask*tmp = pform_make_call_task(@1, *$1, *$2);
|
||||
delete $1;
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
| subroutine_call ';'
|
||||
{ $$ = $1;
|
||||
}
|
||||
|
||||
| hierarchy_identifier K_with '{' constraint_block_item_list_opt '}' ';'
|
||||
|
|
@ -6622,14 +6649,6 @@ statement_item /* This is roughly statement_item in the LRM */
|
|||
$$ = tmp;
|
||||
}
|
||||
|
||||
| class_hierarchy_identifier argument_list_parens_opt ';'
|
||||
{ PCallTask*tmp = new PCallTask(*$1, *$2);
|
||||
FILE_NAME(tmp, @1);
|
||||
delete $1;
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* IEEE1800 A.1.8: class_constructor_declaration with a call to
|
||||
parent constructor. Note that the implicit_class_handle must
|
||||
be K_super ("this.new" makes little sense) but that would
|
||||
|
|
@ -6646,14 +6665,6 @@ statement_item /* This is roughly statement_item in the LRM */
|
|||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| hierarchy_identifier '(' error ')' ';'
|
||||
{ yyerror(@3, "error: Syntax error in task arguments.");
|
||||
list<PExpr*>pt;
|
||||
PCallTask*tmp = pform_make_call_task(@1, *$1, pt);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| error ';'
|
||||
{ yyerror(@2, "error: malformed statement");
|
||||
yyerrok;
|
||||
|
|
|
|||
Loading…
Reference in New Issue