Skip to content

Commit

Permalink
Internals: Add cloneTreePure to prepare for side effect check.
Browse files Browse the repository at this point in the history
Use cloneTreePure when what is being cloned must be side-effect free.
Use cloneTree when safe to contain side effects (e.g. cloning module).
  • Loading branch information
wsnyder committed Sep 17, 2023
1 parent cd1fe64 commit 761adf1
Show file tree
Hide file tree
Showing 25 changed files with 193 additions and 180 deletions.
16 changes: 8 additions & 8 deletions src/V3Assert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ class AssertVisitor final : public VNVisitor {
}

// Build a bitmask of the true predicates
AstNodeExpr* const predp = ifp->condp()->cloneTree(false);
AstNodeExpr* const predp = ifp->condp()->cloneTreePure(false);
if (propp) {
propp = new AstConcat{nodep->fileline(), predp, propp};
} else {
Expand Down Expand Up @@ -312,17 +312,17 @@ class AssertVisitor final : public VNVisitor {
icondp = VN_AS(icondp->nextp(), NodeExpr)) {
AstNodeExpr* onep;
if (AstInsideRange* const rcondp = VN_CAST(icondp, InsideRange)) {
onep = rcondp->newAndFromInside(nodep->exprp(),
rcondp->lhsp()->cloneTree(true),
rcondp->rhsp()->cloneTree(true));
onep = rcondp->newAndFromInside(
nodep->exprp(), rcondp->lhsp()->cloneTreePure(true),
rcondp->rhsp()->cloneTreePure(true));
} else if (nodep->casex() || nodep->casez() || nodep->caseInside()) {
onep = AstEqWild::newTyped(itemp->fileline(),
nodep->exprp()->cloneTree(false),
icondp->cloneTree(false));
nodep->exprp()->cloneTreePure(false),
icondp->cloneTreePure(false));
} else {
onep = AstEq::newTyped(icondp->fileline(),
nodep->exprp()->cloneTree(false),
icondp->cloneTree(false));
nodep->exprp()->cloneTreePure(false),
icondp->cloneTreePure(false));
}
if (propp) {
propp = new AstConcat{icondp->fileline(), onep, propp};
Expand Down
16 changes: 8 additions & 8 deletions src/V3AssertPre.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ class AssertPreVisitor final : public VNVisitor {
if (nodep->direction() == VDirection::OUTPUT) {
AstVarRef* const skewedRefp = new AstVarRef{flp, varp, VAccess::READ};
skewedRefp->user1(true);
AstAssign* const assignp = new AstAssign{flp, exprp->cloneTree(false), skewedRefp};
AstAssign* const assignp = new AstAssign{flp, exprp->cloneTreePure(false), skewedRefp};
if (skewp->isZero()) {
// Drive the var in Re-NBA (IEEE 1800-2017 14.16)
m_clockingp->addNextHere(new AstAlwaysReactive{
Expand Down Expand Up @@ -208,12 +208,12 @@ class AssertPreVisitor final : public VNVisitor {
refp->user1(true);
if (skewp->num().is1Step()) {
// Assign the sampled expression to the clockvar (IEEE 1800-2017 14.13)
AstSampled* const sampledp = new AstSampled{flp, exprp->cloneTree(false)};
AstSampled* const sampledp = new AstSampled{flp, exprp->cloneTreePure(false)};
sampledp->dtypeFrom(exprp);
m_clockingp->addNextHere(new AstAssignW{flp, refp, sampledp});
} else if (skewp->isZero()) {
// #0 means the var has to be sampled in Observed (IEEE 1800-2017 14.13)
AstAssign* const assignp = new AstAssign{flp, refp, exprp->cloneTree(false)};
AstAssign* const assignp = new AstAssign{flp, refp, exprp->cloneTreePure(false)};
m_clockingp->addNextHere(new AstAlwaysObserved{
flp, new AstSenTree{flp, m_clockingp->sensesp()->cloneTree(false)}, assignp});
} else {
Expand All @@ -230,7 +230,7 @@ class AssertPreVisitor final : public VNVisitor {
AstCMethodHard* const pushp = new AstCMethodHard{
flp, new AstVarRef{flp, queueVarp, VAccess::WRITE}, "push",
new AstTime{nodep->fileline(), m_modp->timeunit()}};
pushp->addPinsp(exprp->cloneTree(false));
pushp->addPinsp(exprp->cloneTreePure(false));
pushp->dtypeSetVoid();
m_clockingp->addNextHere(
new AstAlways{flp, VAlwaysKwd::ALWAYS, nullptr, pushp->makeStmt()});
Expand Down Expand Up @@ -372,7 +372,7 @@ class AssertPreVisitor final : public VNVisitor {
if (sentreep) sentreep->unlinkFrBack();
AstNodeExpr* const past = new AstPast{fl, exprp, nullptr};
past->dtypeFrom(exprp);
exprp = new AstAnd{fl, past, new AstNot{fl, exprp->cloneTree(false)}};
exprp = new AstAnd{fl, past, new AstNot{fl, exprp->cloneTreePure(false)}};
exprp->dtypeSetBit();
nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep, sentreep));
Expand All @@ -393,7 +393,7 @@ class AssertPreVisitor final : public VNVisitor {
if (sentreep) sentreep->unlinkFrBack();
AstNodeExpr* const past = new AstPast{fl, exprp, nullptr};
past->dtypeFrom(exprp);
exprp = new AstAnd{fl, new AstNot{fl, past}, exprp->cloneTree(false)};
exprp = new AstAnd{fl, new AstNot{fl, past}, exprp->cloneTreePure(false)};
exprp->dtypeSetBit();
nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep, sentreep));
Expand All @@ -408,7 +408,7 @@ class AssertPreVisitor final : public VNVisitor {
if (sentreep) sentreep->unlinkFrBack();
AstNodeExpr* const past = new AstPast{fl, exprp, nullptr};
past->dtypeFrom(exprp);
exprp = new AstEq{fl, past, exprp->cloneTree(false)};
exprp = new AstEq{fl, past, exprp->cloneTreePure(false)};
exprp->dtypeSetBit();
nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep, sentreep));
Expand Down Expand Up @@ -442,7 +442,7 @@ class AssertPreVisitor final : public VNVisitor {
// Block is the new expression to evaluate
AstNodeExpr* blockp = VN_AS(nodep->propp()->unlinkFrBack(), NodeExpr);
if (AstNodeExpr* const disablep = nodep->disablep()) {
m_disablep = disablep->cloneTree(false);
m_disablep = disablep->cloneTreePure(false);
if (VN_IS(nodep->backp(), Cover)) {
blockp = new AstAnd{disablep->fileline(),
new AstNot{disablep->fileline(), disablep->unlinkFrBack()},
Expand Down
3 changes: 2 additions & 1 deletion src/V3Ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -1998,7 +1998,8 @@ class AstNode VL_NOT_FINAL {
AstNode* belowp); // When calling, "this" is second argument

// METHODS - Iterate on a tree
AstNode* cloneTree(bool cloneNextLink); // Not const, as sets clonep() on original nodep
AstNode* cloneTree(bool cloneNextLink); // Not const, as sets clonep() on original nodep //
AstNode* cloneTreePure(bool cloneNextLink) { return cloneTree(cloneNextLink); }
bool gateTree() { return gateTreeIter(); } // Is tree isGateOptimizable?
inline bool sameTree(const AstNode* node2p) const; // Does tree of this == node2p?
// Does tree of this == node2p?, not allowing non-isGateOptimizable
Expand Down
6 changes: 3 additions & 3 deletions src/V3AstNodeExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4187,10 +4187,10 @@ class AstCountBits final : public AstNodeQuadop {
// Number of bits set in vector
public:
AstCountBits(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ctrl1p)
: ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl1p->cloneTree(false),
ctrl1p->cloneTree(false)) {}
: ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl1p->cloneTreePure(false),
ctrl1p->cloneTreePure(false)) {}
AstCountBits(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ctrl1p, AstNodeExpr* ctrl2p)
: ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl2p->cloneTree(false)) {}
: ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl2p->cloneTreePure(false)) {}
AstCountBits(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ctrl1p, AstNodeExpr* ctrl2p,
AstNodeExpr* ctrl3p)
: ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {}
Expand Down
4 changes: 2 additions & 2 deletions src/V3AstNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,8 @@ AstExecGraph::~AstExecGraph() { VL_DO_DANGLING(delete m_depGraphp, m_depGraphp);

AstNodeExpr* AstInsideRange::newAndFromInside(AstNodeExpr* exprp, AstNodeExpr* lhsp,
AstNodeExpr* rhsp) {
AstNodeExpr* const ap = new AstGte{fileline(), exprp->cloneTree(true), lhsp};
AstNodeExpr* const bp = new AstLte{fileline(), exprp->cloneTree(true), rhsp};
AstNodeExpr* const ap = new AstGte{fileline(), exprp->cloneTreePure(true), lhsp};
AstNodeExpr* const bp = new AstLte{fileline(), exprp->cloneTreePure(true), rhsp};
ap->fileline()->modifyWarnOff(V3ErrorCode::UNSIGNED, true);
bp->fileline()->modifyWarnOff(V3ErrorCode::CMPCONST, true);
return new AstAnd{fileline(), ap, bp};
Expand Down
12 changes: 6 additions & 6 deletions src/V3Case.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,10 +362,10 @@ class CaseVisitor final : public VNVisitor {

// Alternate scheme if we ever do multiple bits at a time:
// V3Number nummask (cexprp, cexprp->width(), (1UL<<msb));
// AstNode* and1p = new AstAnd(cexprp->fileline(), cexprp->cloneTree(false),
// AstNode* and1p = new AstAnd(cexprp->fileline(), cexprp->cloneTreePure(false),
// new AstConst(cexprp->fileline(), nummask));
AstNodeExpr* const and1p
= new AstSel{cexprp->fileline(), cexprp->cloneTree(false), msb, 1};
= new AstSel{cexprp->fileline(), cexprp->cloneTreePure(false), msb, 1};
AstNodeExpr* const eqp
= new AstNeq{cexprp->fileline(), new AstConst{cexprp->fileline(), 0}, and1p};
AstIf* const ifp = new AstIf{cexprp->fileline(), eqp, tree1p, tree0p};
Expand Down Expand Up @@ -450,7 +450,7 @@ class CaseVisitor final : public VNVisitor {
V3Number numval{itemp, iconstp->width()};
numval.opBitsOne(iconstp->num());
AstNodeExpr* const and1p
= new AstAnd{itemp->fileline(), cexprp->cloneTree(false),
= new AstAnd{itemp->fileline(), cexprp->cloneTreePure(false),
new AstConst{itemp->fileline(), nummask}};
AstNodeExpr* const and2p = new AstAnd{
itemp->fileline(), new AstConst{itemp->fileline(), numval},
Expand All @@ -460,7 +460,7 @@ class CaseVisitor final : public VNVisitor {
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
} else {
// Not a caseX mask, we can build CASEEQ(cexpr icond)
AstNodeExpr* const and1p = cexprp->cloneTree(false);
AstNodeExpr* const and1p = cexprp->cloneTreePure(false);
AstNodeExpr* const and2p = icondp;
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
}
Expand Down Expand Up @@ -502,7 +502,7 @@ class CaseVisitor final : public VNVisitor {
if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1;
if (depth == 1) { // First group or starting new group
itemnextp = nullptr;
AstIf* const newp = new AstIf{itemp->fileline(), ifexprp->cloneTree(true)};
AstIf* const newp = new AstIf{itemp->fileline(), ifexprp->cloneTreePure(true)};
if (groupnextp) {
groupnextp->addElsesp(newp);
} else {
Expand All @@ -512,7 +512,7 @@ class CaseVisitor final : public VNVisitor {
} else { // Continue group, modify if condition to OR in this new condition
AstNodeExpr* const condp = groupnextp->condp()->unlinkFrBack();
groupnextp->condp(
new AstOr{ifexprp->fileline(), condp, ifexprp->cloneTree(true)});
new AstOr{ifexprp->fileline(), condp, ifexprp->cloneTreePure(true)});
}
}
{ // Make the new lower IF and attach in the tree
Expand Down
26 changes: 13 additions & 13 deletions src/V3Const.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1494,13 +1494,13 @@ class ConstVisitor final : public VNVisitor {
const AstSel* rselp = VN_CAST(rhsp, Sel);
// a[i:0] a
if (lselp && !rselp && rhsp->sameGateTree(lselp->fromp()))
rselp = new AstSel{rhsp->fileline(), rhsp->cloneTree(false), 0, rhsp->width()};
rselp = new AstSel{rhsp->fileline(), rhsp->cloneTreePure(false), 0, rhsp->width()};
// a[i:j] {a[j-1:k], b}
if (lselp && !rselp && VN_IS(rhsp, Concat))
return ifMergeAdjacent(lhsp, VN_CAST(rhsp, Concat)->lhsp());
// a a[msb:j]
if (rselp && !lselp && lhsp->sameGateTree(rselp->fromp()))
lselp = new AstSel{lhsp->fileline(), lhsp->cloneTree(false), 0, lhsp->width()};
lselp = new AstSel{lhsp->fileline(), lhsp->cloneTreePure(false), 0, lhsp->width()};
// {b, a[j:k]} a[k-1:i]
if (rselp && !lselp && VN_IS(lhsp, Concat))
return ifMergeAdjacent(VN_CAST(lhsp, Concat)->rhsp(), rhsp);
Expand Down Expand Up @@ -1812,10 +1812,10 @@ class ConstVisitor final : public VNVisitor {
// {llp OP lrp, rlp OP rrp} => {llp, rlp} OP {lrp, rrp}, where OP = AND/OR/XOR
AstNodeBiop* const lp = VN_AS(nodep->lhsp(), NodeBiop);
AstNodeBiop* const rp = VN_AS(nodep->rhsp(), NodeBiop);
AstNodeExpr* const llp = lp->lhsp()->cloneTree(false);
AstNodeExpr* const lrp = lp->rhsp()->cloneTree(false);
AstNodeExpr* const rlp = rp->lhsp()->cloneTree(false);
AstNodeExpr* const rrp = rp->rhsp()->cloneTree(false);
AstNodeExpr* const llp = lp->lhsp()->cloneTreePure(false);
AstNodeExpr* const lrp = lp->rhsp()->cloneTreePure(false);
AstNodeExpr* const rlp = rp->lhsp()->cloneTreePure(false);
AstNodeExpr* const rrp = rp->rhsp()->cloneTreePure(false);
if (concatMergeable(lp, rp, 0)) {
AstConcat* const newlp = new AstConcat{rlp->fileline(), llp, rlp};
AstConcat* const newrp = new AstConcat{rrp->fileline(), lrp, rrp};
Expand Down Expand Up @@ -1897,9 +1897,9 @@ class ConstVisitor final : public VNVisitor {
AstNodeExpr* const ap = lhsp->lhsp()->unlinkFrBack();
AstNodeExpr* const bp = lhsp->rhsp()->unlinkFrBack();
AstNodeBiop* const shift1p = nodep;
AstNodeBiop* const shift2p = nodep->cloneTree(true);
AstNodeBiop* const shift2p = nodep->cloneTreePure(true);
shift1p->lhsp(ap);
shift1p->rhsp(shiftp->cloneTree(true));
shift1p->rhsp(shiftp->cloneTreePure(true));
shift2p->lhsp(bp);
shift2p->rhsp(shiftp);
AstNodeBiop* const newp = lhsp;
Expand Down Expand Up @@ -2085,7 +2085,7 @@ class ConstVisitor final : public VNVisitor {
AstNodeExpr* const lc2p = VN_AS(nodep->lhsp(), Concat)->rhsp()->unlinkFrBack();
AstNodeExpr* const conp = VN_AS(nodep->lhsp(), Concat)->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const rhs2p = rhsp->cloneTree(false);
AstNodeExpr* const rhs2p = rhsp->cloneTreePure(false);
// Calc widths
const int lsb2 = 0;
const int msb2 = lsb2 + lc2p->width() - 1;
Expand Down Expand Up @@ -2430,8 +2430,8 @@ class ConstVisitor final : public VNVisitor {
nodep->fileline(),
new AstLogOr{nodep->fileline(), new AstLogNot{nodep->fileline(), lhsp}, rhsp},
new AstLogOr{nodep->fileline(),
new AstLogNot{nodep->fileline(), rhsp->cloneTree(false)},
lhsp->cloneTree(false)}};
new AstLogNot{nodep->fileline(), rhsp->cloneTreePure(false)},
lhsp->cloneTreePure(false)}};
newp->dtypeFrom(nodep);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
Expand Down Expand Up @@ -2588,8 +2588,8 @@ class ConstVisitor final : public VNVisitor {
AstNodeExpr* const bilhsp = fromp->lhsp()->unlinkFrBack();
AstNodeExpr* const birhsp = fromp->rhsp()->unlinkFrBack();
//
fromp->lhsp(
new AstSel{nodep->fileline(), bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)});
fromp->lhsp(new AstSel{nodep->fileline(), bilhsp, lsbp->cloneTreePure(true),
widthp->cloneTreePure(true)});
fromp->rhsp(new AstSel{nodep->fileline(), birhsp, lsbp, widthp});
fromp->dtypeFrom(nodep);
nodep->replaceWith(fromp);
Expand Down
2 changes: 1 addition & 1 deletion src/V3Delayed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ class DelayedVisitor final : public VNVisitor {
}
if (bitselp) {
selectsp = new AstSel{nodep->fileline(), selectsp, bitreadp,
bitselp->widthp()->cloneTree(false)};
bitselp->widthp()->cloneTreePure(false)}; // Always pure
}
// Build "IF (changeit) ...
UINFO(9, " For " << setvscp << endl);
Expand Down
4 changes: 2 additions & 2 deletions src/V3DfgDfgToAst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ class DfgToAstVisitor final : DfgVisitor {
FileLine* const flp = dfgVarp->driverFileLine(idx);
AstConst* const lsbp = new AstConst{flp, dfgVarp->driverLsb(idx)};
AstConst* const widthp = new AstConst{flp, edge.sourcep()->width()};
AstSel* const rhsp = new AstSel{flp, rRef(), lsbp, widthp->cloneTree(false)};
AstSel* const lhsp = new AstSel{flp, wRef(), lsbp->cloneTree(false), widthp};
AstSel* const rhsp = new AstSel{flp, rRef(), lsbp, widthp->cloneTreePure(false)};
AstSel* const lhsp = new AstSel{flp, wRef(), lsbp->cloneTreePure(false), widthp};
// Add assignment of the value to the selected bits
addResultEquation(flp, lhsp, rhsp);
});
Expand Down
Loading

0 comments on commit 761adf1

Please sign in to comment.