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:
Ryszard Rozak 2023-01-31 04:20:56 +01:00 committed by GitHub
parent 87a7881d46
commit 7f3e178b68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 32 deletions

View File

@ -2350,6 +2350,7 @@ private:
// Dot(Dot(Dot(ParseRef(text), ...
if (nodep->user3SetOnce()) return;
UINFO(8, " " << nodep << endl);
bool replaceWithRhs = true;
const DotStates lastStates = m_ds;
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())) {
// Dots of paramed classes will be linked after deparameterization
m_ds.m_dotPos = DP_NONE;
return;
m_ds.m_unresolved = true;
replaceWithRhs = false;
}
if (m_ds.m_unresolved
&& (VN_IS(nodep->lhsp(), CellRef) || VN_IS(nodep->lhsp(), CellArrayRef))) {
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
// Top 'final' dot RHS is final RHS, else it's a
// DOT(DOT(x,*here*),real-rhs) which we consider a RHS
@ -2417,16 +2417,17 @@ private:
// if (debug() >= 9) nodep->dumpTree("- dot-rho: ");
}
if (start) {
AstNode* newp;
if (m_ds.m_dotErr) {
newp = new AstConst{nodep->fileline(), AstConst::BitFalse{}};
} else {
// RHS is what we're left with
newp = nodep->rhsp()->unlinkFrBack();
if (replaceWithRhs) {
AstNode* newp;
if (m_ds.m_dotErr) {
newp = new AstConst{nodep->fileline(), AstConst::BitFalse{}};
} else {
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
AstNodeExpr* newp = nodep->rhsp()->unlinkFrBack();
if (m_ds.m_unresolved) {
@ -2452,6 +2453,7 @@ private:
void visit(AstParseRef* nodep) override {
if (nodep->user3SetOnce()) return;
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_ds.m_dotSymp is symbol table relative to "."'s above now
UASSERT_OBJ(m_ds.m_dotSymp, nodep, "nullptr lookup symbol table");
@ -2492,7 +2494,7 @@ private:
// If not, treat it as normal member select
iterateChildren(nodep);
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);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;
@ -2941,7 +2943,29 @@ private:
if (nodep->user3SetOnce()) return;
UINFO(8, " " << nodep << 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(),
"Bad package link");
AstClassOrPackageRef* const cpackagerefp
@ -2955,19 +2979,7 @@ private:
m_ds.m_dotPos = DP_SCOPE;
m_ds.m_dotp = nullptr;
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_FINAL) {
if (m_ds.m_unresolved && 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);
return;
} else {
nodep->dotted(m_ds.m_dotText); // Maybe ""
}
nodep->dotted(m_ds.m_dotText); // Maybe ""
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_MEMBER) {
// Found a Var, everything following is method call.
// {scope}.{var}.HERE {method} ( ARGS )
@ -3098,11 +3110,6 @@ private:
}
taskFuncSwapCheck(nodep);
}
{
VL_RESTORER(m_ds);
m_ds.init(m_curSymp);
iterateChildren(nodep);
}
}
void visit(AstSelBit* nodep) override {
if (nodep->user3SetOnce()) return;

View File

@ -54,6 +54,22 @@ class SelfRefClassIntParam #(int P=1);
typedef SelfRefClassIntParam #(10) self_int_t;
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*/);
Cls c12;
@ -65,6 +81,8 @@ module t (/*AUTOARG*/);
SelfRefClassTypeParam::self_int_t src_int;
SelfRefClassIntParam src1;
SelfRefClassIntParam::self_int_t src10;
IntQueue qi;
int arr [1:0] = '{1, 2};
initial begin
c12 = new;
c4 = new;
@ -75,6 +93,7 @@ module t (/*AUTOARG*/);
src_logic = new;
src1 = new;
src10 = new;
qi = new;
if (Cls#()::PBASE != 12) $stop;
if (Cls#(4)::PBASE != 4) $stop;
if (Cls8_t::PBASE != 8) $stop;
@ -114,6 +133,12 @@ module t (/*AUTOARG*/);
if (src1.P != 1) $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");
$finish;
end