unify walk into single pass
This commit is contained in:
parent
8f935ec3aa
commit
dce1c8d165
|
|
@ -2190,62 +2190,50 @@ public:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve `class::member` Dots depended on by `rootp`'s tree, and also recursively through
|
// Walk every subtree reachable from `rootp` for three kinds of deferred work
|
||||||
// VarRefs to all leaf dependencies. Then resolve these to typedefs.
|
// V3LinkDot left behind when `class#(...)::member` couldn't yet be resolved:
|
||||||
|
// (1) `AstDot` with a ClassOrPackageRef lhs — a `class::lparam` value Dot to
|
||||||
|
// constify (e.g. `c8::b` in a pin expression).
|
||||||
|
// (2) `AstRefDType` with a typedefp — descend into the typedef's subDType
|
||||||
|
// to find buried Dots (typedef range like `logic [(CFG::w - 1):0]`) and
|
||||||
|
// unresolved class-scoped struct-member RefDTypes (`CFG::input_meta_t`
|
||||||
|
// as a struct member).
|
||||||
|
// (3) `AstVarRef` to a deferred lparam — descend into its valuep so the
|
||||||
|
// chain `pin -> lparam -> ... -> class::lparam Dot` reaches the Dot.
|
||||||
|
// Discoveries of (2) and (3) feed back into the walk worklist; (1) and (2)
|
||||||
|
// are also kept in lists for the resolution passes at the end.
|
||||||
void resolveDeferredDotsReachableFrom(AstNode* rootp, AstNodeModule* modp) {
|
void resolveDeferredDotsReachableFrom(AstNode* rootp, AstNodeModule* modp) {
|
||||||
std::vector<AstDot*> dotps;
|
std::vector<AstDot*> dotps;
|
||||||
std::vector<AstTypedef*> tdefps;
|
std::vector<AstTypedef*> tdefps;
|
||||||
const auto& deferredVarps = v3Global.rootp()->deferredParamVarps();
|
const auto& deferredVarps = v3Global.rootp()->deferredParamVarps();
|
||||||
std::set<AstVar*> reachedDeferred;
|
std::set<AstVar*> reachedDeferred;
|
||||||
std::set<const AstTypedef*> reachedTypedefs;
|
std::set<const AstTypedef*> reachedTypedefs;
|
||||||
auto collectDots = [&](AstNode* p) {
|
std::vector<AstNode*> worklist{rootp};
|
||||||
|
while (!worklist.empty()) {
|
||||||
|
AstNode* const p = worklist.back();
|
||||||
|
worklist.pop_back();
|
||||||
p->foreach([&](AstDot* dotp) {
|
p->foreach([&](AstDot* dotp) {
|
||||||
if (VN_IS(dotp->lhsp(), ClassOrPackageRef)) dotps.push_back(dotp);
|
if (VN_IS(dotp->lhsp(), ClassOrPackageRef)) dotps.push_back(dotp);
|
||||||
});
|
});
|
||||||
};
|
|
||||||
auto collectTypedefs = [&](AstNode* p) {
|
|
||||||
p->foreach([&](const AstRefDType* refp) {
|
p->foreach([&](const AstRefDType* refp) {
|
||||||
AstTypedef* const tdefp = refp->typedefp();
|
AstTypedef* const tdefp = refp->typedefp();
|
||||||
if (tdefp && reachedTypedefs.insert(tdefp).second) tdefps.push_back(tdefp);
|
if (tdefp && reachedTypedefs.insert(tdefp).second) {
|
||||||
});
|
tdefps.push_back(tdefp);
|
||||||
};
|
if (tdefp->subDTypep()) worklist.push_back(tdefp->subDTypep());
|
||||||
std::vector<AstVar*> workVarps;
|
}
|
||||||
auto enqueueRefs = [&](AstNode* p) {
|
});
|
||||||
p->foreach([&](const AstVarRef* refp) {
|
p->foreach([&](const AstVarRef* refp) {
|
||||||
AstVar* const refVarp = refp->varp();
|
AstVar* const varp = refp->varp();
|
||||||
if (refVarp && refVarp->varType() == VVarType::LPARAM
|
if (varp && varp->varType() == VVarType::LPARAM && deferredVarps.count(varp)
|
||||||
&& deferredVarps.count(refVarp) && reachedDeferred.insert(refVarp).second) {
|
&& reachedDeferred.insert(varp).second && varp->valuep()) {
|
||||||
workVarps.push_back(refVarp);
|
worklist.push_back(varp->valuep());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
|
||||||
collectDots(rootp);
|
|
||||||
collectTypedefs(rootp);
|
|
||||||
enqueueRefs(rootp);
|
|
||||||
// Handle deferred VarRefs recursively until no more, accumulating Dots and
|
|
||||||
// typedef references along the way.
|
|
||||||
while (!workVarps.empty()) {
|
|
||||||
AstVar* const varp = workVarps.back();
|
|
||||||
workVarps.pop_back();
|
|
||||||
if (!varp->valuep()) continue;
|
|
||||||
collectDots(varp->valuep());
|
|
||||||
collectTypedefs(varp->valuep());
|
|
||||||
enqueueRefs(varp->valuep());
|
|
||||||
}
|
|
||||||
// Descend into each collected typedef's subDType for Dots (e.g. class-scoped
|
|
||||||
// lparams used in a packed range like `logic [(CFG::pc_width - 1):0]`) and
|
|
||||||
// nested typedef references. The loop grows tdefps as it goes; the
|
|
||||||
// `i < tdefps.size()` re-check carries us to fixpoint.
|
|
||||||
for (size_t i = 0; i < tdefps.size(); ++i) {
|
|
||||||
AstNodeDType* const subp = tdefps[i]->subDTypep();
|
|
||||||
if (!subp) continue;
|
|
||||||
collectDots(subp);
|
|
||||||
collectTypedefs(subp);
|
|
||||||
}
|
}
|
||||||
if (dotps.empty() && tdefps.empty()) return;
|
if (dotps.empty() && tdefps.empty()) return;
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
m_modp = modp;
|
m_modp = modp;
|
||||||
// Resolve unresolved class-scoped RefDTypes buried in any typedef reachable from
|
// Link unresolved class-scoped RefDTypes buried in any typedef reachable from
|
||||||
// the pin/expr tree (e.g. `$bits(wrap_t)` where `wrap_t`'s struct members
|
// the pin/expr tree (e.g. `$bits(wrap_t)` where `wrap_t`'s struct members
|
||||||
// reference `CFG::data_t` from a parameterized-class typedef alias).
|
// reference `CFG::data_t` from a parameterized-class typedef alias).
|
||||||
for (AstTypedef* const tdefp : tdefps) resolveParamClassRefDType(tdefp->subDTypep());
|
for (AstTypedef* const tdefp : tdefps) resolveParamClassRefDType(tdefp->subDTypep());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue