Fix paramaterized class function linkage (#3917)
* Visit function arguments even if the function is unlinkable * Don't use m_unlinedScopep in AstLambdaArgRef handling
This commit is contained in:
parent
87a7881d46
commit
7f3e178b68
|
|
@ -2350,6 +2350,7 @@ private:
|
||||||
// Dot(Dot(Dot(ParseRef(text), ...
|
// Dot(Dot(Dot(ParseRef(text), ...
|
||||||
if (nodep->user3SetOnce()) return;
|
if (nodep->user3SetOnce()) return;
|
||||||
UINFO(8, " " << nodep << endl);
|
UINFO(8, " " << nodep << endl);
|
||||||
|
bool replaceWithRhs = true;
|
||||||
const DotStates lastStates = m_ds;
|
const DotStates lastStates = m_ds;
|
||||||
const bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed
|
const bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed
|
||||||
{
|
{
|
||||||
|
|
@ -2401,14 +2402,13 @@ private:
|
||||||
}
|
}
|
||||||
if (m_statep->forPrimary() && isParamedClassRef(nodep->lhsp())) {
|
if (m_statep->forPrimary() && isParamedClassRef(nodep->lhsp())) {
|
||||||
// Dots of paramed classes will be linked after deparameterization
|
// Dots of paramed classes will be linked after deparameterization
|
||||||
m_ds.m_dotPos = DP_NONE;
|
m_ds.m_unresolved = true;
|
||||||
return;
|
replaceWithRhs = false;
|
||||||
}
|
}
|
||||||
if (m_ds.m_unresolved
|
if (m_ds.m_unresolved
|
||||||
&& (VN_IS(nodep->lhsp(), CellRef) || VN_IS(nodep->lhsp(), CellArrayRef))) {
|
&& (VN_IS(nodep->lhsp(), CellRef) || VN_IS(nodep->lhsp(), CellArrayRef))) {
|
||||||
m_ds.m_unlinkedScopep = nodep->lhsp();
|
m_ds.m_unlinkedScopep = nodep->lhsp();
|
||||||
}
|
}
|
||||||
if (VN_IS(nodep->lhsp(), LambdaArgRef)) m_ds.m_unlinkedScopep = nodep->lhsp();
|
|
||||||
if (!m_ds.m_dotErr) { // Once something wrong, give up
|
if (!m_ds.m_dotErr) { // Once something wrong, give up
|
||||||
// Top 'final' dot RHS is final RHS, else it's a
|
// Top 'final' dot RHS is final RHS, else it's a
|
||||||
// DOT(DOT(x,*here*),real-rhs) which we consider a RHS
|
// DOT(DOT(x,*here*),real-rhs) which we consider a RHS
|
||||||
|
|
@ -2417,16 +2417,17 @@ private:
|
||||||
// if (debug() >= 9) nodep->dumpTree("- dot-rho: ");
|
// if (debug() >= 9) nodep->dumpTree("- dot-rho: ");
|
||||||
}
|
}
|
||||||
if (start) {
|
if (start) {
|
||||||
AstNode* newp;
|
if (replaceWithRhs) {
|
||||||
if (m_ds.m_dotErr) {
|
AstNode* newp;
|
||||||
newp = new AstConst{nodep->fileline(), AstConst::BitFalse{}};
|
if (m_ds.m_dotErr) {
|
||||||
} else {
|
newp = new AstConst{nodep->fileline(), AstConst::BitFalse{}};
|
||||||
// RHS is what we're left with
|
} else {
|
||||||
newp = nodep->rhsp()->unlinkFrBack();
|
newp = nodep->rhsp()->unlinkFrBack();
|
||||||
|
}
|
||||||
|
if (debug() >= 9) newp->dumpTree("- dot-out: ");
|
||||||
|
nodep->replaceWith(newp);
|
||||||
|
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||||
}
|
}
|
||||||
if (debug() >= 9) newp->dumpTree("- dot-out: ");
|
|
||||||
nodep->replaceWith(newp);
|
|
||||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
|
||||||
} else { // Dot midpoint
|
} else { // Dot midpoint
|
||||||
AstNodeExpr* newp = nodep->rhsp()->unlinkFrBack();
|
AstNodeExpr* newp = nodep->rhsp()->unlinkFrBack();
|
||||||
if (m_ds.m_unresolved) {
|
if (m_ds.m_unresolved) {
|
||||||
|
|
@ -2452,6 +2453,7 @@ private:
|
||||||
void visit(AstParseRef* nodep) override {
|
void visit(AstParseRef* nodep) override {
|
||||||
if (nodep->user3SetOnce()) return;
|
if (nodep->user3SetOnce()) return;
|
||||||
UINFO(9, " linkPARSEREF " << m_ds.ascii() << " n=" << nodep << endl);
|
UINFO(9, " linkPARSEREF " << m_ds.ascii() << " n=" << nodep << endl);
|
||||||
|
if (m_ds.m_unresolved && !m_ds.m_unlinkedScopep) return;
|
||||||
// m_curSymp is symbol table of outer expression
|
// m_curSymp is symbol table of outer expression
|
||||||
// m_ds.m_dotSymp is symbol table relative to "."'s above now
|
// m_ds.m_dotSymp is symbol table relative to "."'s above now
|
||||||
UASSERT_OBJ(m_ds.m_dotSymp, nodep, "nullptr lookup symbol table");
|
UASSERT_OBJ(m_ds.m_dotSymp, nodep, "nullptr lookup symbol table");
|
||||||
|
|
@ -2492,7 +2494,7 @@ private:
|
||||||
// If not, treat it as normal member select
|
// If not, treat it as normal member select
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
const auto newp = new AstLambdaArgRef{
|
const auto newp = new AstLambdaArgRef{
|
||||||
nodep->fileline(), m_ds.m_unlinkedScopep->name() + "__DOT__index", true};
|
nodep->fileline(), m_ds.m_dotp->lhsp()->name() + "__DOT__index", true};
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||||
return;
|
return;
|
||||||
|
|
@ -2941,7 +2943,29 @@ private:
|
||||||
if (nodep->user3SetOnce()) return;
|
if (nodep->user3SetOnce()) return;
|
||||||
UINFO(8, " " << nodep << endl);
|
UINFO(8, " " << nodep << endl);
|
||||||
UINFO(8, " " << m_ds.ascii() << endl);
|
UINFO(8, " " << m_ds.ascii() << endl);
|
||||||
if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) {
|
{
|
||||||
|
// Visit arguments at the beginning.
|
||||||
|
// They may be visitted even if the current node can't be linked now.
|
||||||
|
VL_RESTORER(m_ds);
|
||||||
|
m_ds.init(m_curSymp);
|
||||||
|
iterateChildren(nodep);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ds.m_unresolved) {
|
||||||
|
// Unable to link before V3Param
|
||||||
|
if (m_ds.m_dotPos == DP_FINAL && m_ds.m_unlinkedScopep) {
|
||||||
|
AstNodeFTaskRef* const newftaskp = nodep->cloneTree(false);
|
||||||
|
newftaskp->dotted(m_ds.m_dotText);
|
||||||
|
AstNode* const newp
|
||||||
|
= new AstUnlinkedRef{nodep->fileline(), newftaskp, nodep->name(),
|
||||||
|
m_ds.m_unlinkedScopep->unlinkFrBack()};
|
||||||
|
m_ds.m_unlinkedScopep = nullptr;
|
||||||
|
m_ds.m_unresolved = false;
|
||||||
|
nodep->replaceWith(newp);
|
||||||
|
}
|
||||||
|
// else: AstDot wasn't replaced and it will be linked after V3Param
|
||||||
|
return;
|
||||||
|
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) {
|
||||||
UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(),
|
UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(),
|
||||||
"Bad package link");
|
"Bad package link");
|
||||||
AstClassOrPackageRef* const cpackagerefp
|
AstClassOrPackageRef* const cpackagerefp
|
||||||
|
|
@ -2955,19 +2979,7 @@ private:
|
||||||
m_ds.m_dotPos = DP_SCOPE;
|
m_ds.m_dotPos = DP_SCOPE;
|
||||||
m_ds.m_dotp = nullptr;
|
m_ds.m_dotp = nullptr;
|
||||||
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_FINAL) {
|
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_FINAL) {
|
||||||
if (m_ds.m_unresolved && m_ds.m_unlinkedScopep) {
|
nodep->dotted(m_ds.m_dotText); // Maybe ""
|
||||||
AstNodeFTaskRef* const newftaskp = nodep->cloneTree(false);
|
|
||||||
newftaskp->dotted(m_ds.m_dotText);
|
|
||||||
AstNode* const newp
|
|
||||||
= new AstUnlinkedRef{nodep->fileline(), newftaskp, nodep->name(),
|
|
||||||
m_ds.m_unlinkedScopep->unlinkFrBack()};
|
|
||||||
m_ds.m_unlinkedScopep = nullptr;
|
|
||||||
m_ds.m_unresolved = false;
|
|
||||||
nodep->replaceWith(newp);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
nodep->dotted(m_ds.m_dotText); // Maybe ""
|
|
||||||
}
|
|
||||||
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_MEMBER) {
|
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_MEMBER) {
|
||||||
// Found a Var, everything following is method call.
|
// Found a Var, everything following is method call.
|
||||||
// {scope}.{var}.HERE {method} ( ARGS )
|
// {scope}.{var}.HERE {method} ( ARGS )
|
||||||
|
|
@ -3098,11 +3110,6 @@ private:
|
||||||
}
|
}
|
||||||
taskFuncSwapCheck(nodep);
|
taskFuncSwapCheck(nodep);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
VL_RESTORER(m_ds);
|
|
||||||
m_ds.init(m_curSymp);
|
|
||||||
iterateChildren(nodep);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void visit(AstSelBit* nodep) override {
|
void visit(AstSelBit* nodep) override {
|
||||||
if (nodep->user3SetOnce()) return;
|
if (nodep->user3SetOnce()) return;
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,22 @@ class SelfRefClassIntParam #(int P=1);
|
||||||
typedef SelfRefClassIntParam #(10) self_int_t;
|
typedef SelfRefClassIntParam #(10) self_int_t;
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
|
class Sum #(type T);
|
||||||
|
static int sum;
|
||||||
|
static function void add(T element);
|
||||||
|
sum += int'(element);
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class IntQueue;
|
||||||
|
int q[$];
|
||||||
|
function int getSum();
|
||||||
|
foreach(q[i])
|
||||||
|
Sum#(int)::add(q[i]);
|
||||||
|
return Sum#(int)::sum;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
module t (/*AUTOARG*/);
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
Cls c12;
|
Cls c12;
|
||||||
|
|
@ -65,6 +81,8 @@ module t (/*AUTOARG*/);
|
||||||
SelfRefClassTypeParam::self_int_t src_int;
|
SelfRefClassTypeParam::self_int_t src_int;
|
||||||
SelfRefClassIntParam src1;
|
SelfRefClassIntParam src1;
|
||||||
SelfRefClassIntParam::self_int_t src10;
|
SelfRefClassIntParam::self_int_t src10;
|
||||||
|
IntQueue qi;
|
||||||
|
int arr [1:0] = '{1, 2};
|
||||||
initial begin
|
initial begin
|
||||||
c12 = new;
|
c12 = new;
|
||||||
c4 = new;
|
c4 = new;
|
||||||
|
|
@ -75,6 +93,7 @@ module t (/*AUTOARG*/);
|
||||||
src_logic = new;
|
src_logic = new;
|
||||||
src1 = new;
|
src1 = new;
|
||||||
src10 = new;
|
src10 = new;
|
||||||
|
qi = new;
|
||||||
if (Cls#()::PBASE != 12) $stop;
|
if (Cls#()::PBASE != 12) $stop;
|
||||||
if (Cls#(4)::PBASE != 4) $stop;
|
if (Cls#(4)::PBASE != 4) $stop;
|
||||||
if (Cls8_t::PBASE != 8) $stop;
|
if (Cls8_t::PBASE != 8) $stop;
|
||||||
|
|
@ -114,6 +133,12 @@ module t (/*AUTOARG*/);
|
||||||
if (src1.P != 1) $stop;
|
if (src1.P != 1) $stop;
|
||||||
if (src10.P != 10) $stop;
|
if (src10.P != 10) $stop;
|
||||||
|
|
||||||
|
qi.q = '{2, 4, 6, 0, 2};
|
||||||
|
if (qi.getSum() != 14) $stop;
|
||||||
|
Sum#(int)::add(arr[0]);
|
||||||
|
if(Sum#(int)::sum != 16) $stop;
|
||||||
|
if(Sum#(real)::sum != 0) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue