Fix internal error on xrefs into unrolled functions, bug1387.

This commit is contained in:
Wilson Snyder 2019-01-06 17:38:27 -05:00
parent aaf5b7c2c0
commit 62a7d713a7
15 changed files with 96 additions and 15 deletions

View File

@ -19,6 +19,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix uninitialized data in verFiles and unroller, bug1385. bug1386. [Al Grant]
**** Fix internal error on xrefs into unrolled functions, bug1387. [Al Grant]
* Verilator 4.008 2018-12-01

View File

@ -452,10 +452,10 @@ implementation is not found, the system will look in turn for overloaded
implementations up the inheritance hierarchy. For example calling C<accept>
on C<AstIf> will look in turn for:
void visit (AstIf* nodep)
void visit (AstNodeIf* nodep)
void visit (AstNodeStmt* nodep)
void visit (AstNode* nodep)
void visit(AstIf* nodep)
void visit(AstNodeIf* nodep)
void visit(AstNodeStmt* nodep)
void visit(AstNode* nodep)
There are three ways data is passed between visitor functions.

View File

@ -1642,6 +1642,7 @@ public:
: AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeStmt)
// METHODS
virtual bool isStatement() const { return true; } // Really a statement
virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
};
@ -2067,8 +2068,9 @@ public:
bool pure() const { return m_pure; }
};
class AstNodeFTaskRef : public AstNode {
class AstNodeFTaskRef : public AstNodeStmt {
// A reference to a task (or function)
// Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal.
private:
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
string m_name; // Name of variable
@ -2077,12 +2079,12 @@ private:
AstPackage* m_packagep; // Package hierarchy
public:
AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp)
: AstNode(fl)
: AstNodeStmt(fl)
, m_taskp(NULL), m_packagep(NULL) {
setOp1p(namep); addNOp2p(pinsp);
}
AstNodeFTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
: AstNode(fl)
: AstNodeStmt(fl)
, m_taskp(NULL), m_name(name), m_packagep(NULL) {
addNOp2p(pinsp);
}

View File

@ -2026,6 +2026,7 @@ public:
AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
:AstNodeFTaskRef(fl, name, pinsp) {}
ASTNODE_NODE_FUNCS(TaskRef)
virtual bool isStatement() const { return true; } // A statement, unlike FuncRef
};
class AstFuncRef : public AstNodeFTaskRef {
@ -2036,6 +2037,7 @@ public:
AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp)
:AstNodeFTaskRef(fl, name, pinsp) {}
ASTNODE_NODE_FUNCS(FuncRef)
virtual bool isStatement() const { return false; } // Not a statement, unlike TaskRef
virtual bool hasDType() const { return true; }
};

View File

@ -273,6 +273,10 @@ class GaterBodyVisitor : public GaterBaseVisitor {
// (We may get empty IFs but the constant propagater will rip them up for us)
virtual void visit(AstNodeStmt* nodep) {
if (!nodep->isStatement()) {
iterateChildren(nodep);
return;
}
uint32_t oldstate = m_state;
// Find if children want to delete this or not.
// Note children may bicker, and want to both keep and delete (branches on a if)

View File

@ -433,6 +433,10 @@ private:
m_funcp = NULL;
}
virtual void visit(AstNodeStmt* nodep) {
if (!nodep->isStatement()) {
iterateChildren(nodep);
return;
}
if (m_state == STATE_HASH && m_funcp) {
hashStatement(nodep);
}

View File

@ -102,7 +102,11 @@ private:
m_stmtp = NULL;
}
virtual void visit(AstNodeStmt* nodep) {
visitStmt(nodep);
if (!nodep->isStatement()) {
iterateChildren(nodep);
} else {
visitStmt(nodep);
}
}
// Operators
virtual void visit(AstNodeTermop* nodep) {

View File

@ -107,7 +107,11 @@ private:
m_depth--;
}
virtual void visit(AstNodeStmt* nodep) {
visitStmt(nodep);
if (!nodep->isStatement()) {
iterateChildren(nodep);
} else {
visitStmt(nodep);
}
}
virtual void visit(AstNodeMath* nodep) {} // Accelerate

View File

@ -871,6 +871,10 @@ private:
virtual void visit(AstNodeStmt* nodep) {
if (nodep->user1SetOnce()) return; // Process once
if (!nodep->isStatement()) {
iterateChildren(nodep);
return;
}
m_stmtp = nodep;
iterateChildren(nodep);
m_stmtp = NULL;

View File

@ -241,8 +241,12 @@ private:
m_stmtp = NULL;
}
virtual void visit(AstNodeStmt* nodep) {
UINFO(4," STMT "<<nodep<<endl);
startStatement(nodep);
if (!nodep->isStatement()) {
iterateChildren(nodep);
return;
}
UINFO(4," STMT "<<nodep<<endl);
startStatement(nodep);
iterateChildren(nodep);
m_stmtp = NULL;
}

View File

@ -96,6 +96,10 @@ private:
}
}
virtual void visit(AstNodeStmt* nodep) {
if (!nodep->isStatement()) {
iterateChildren(nodep);
return;
}
UINFO(6," CL STMT "<<nodep<<endl);
bool oldKeep = m_keepStmt;
{

View File

@ -1256,6 +1256,10 @@ private:
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin.cpp");
}
virtual void visit(AstNodeStmt* nodep) {
if (!nodep->isStatement()) {
iterateChildren(nodep);
return;
}
m_insMode = IM_BEFORE;
m_insStmtp = nodep;
iterateChildren(nodep);

View File

@ -135,10 +135,10 @@ private:
new AstVarRef(fl, varp, false)))),
NULL);
newp->branchPred(AstBranchPred::BP_LIKELY);
if (debug()>=9) newp->dumpTree(cout," _new: ");
abovep->addNextStmt(newp,abovep);
prep->user2p(newp); // Save so we may LogAnd it next time
}
if (debug()>=9) newp->dumpTree(cout," _new: ");
abovep->addNextStmt(newp, abovep);
prep->user2p(newp); // Save so we may LogAnd it next time
}
}
// VISITORS

20
test_regress/t/t_func_unit.pl Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,23 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
task tsk(output fo);
assign fo = 1'b0;
endtask
module t (/*AUTOARG*/
// Outputs
to
);
output to[2:0];
integer i = 0;
initial begin
tsk(to[i]);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule