Internals: Add cloneTreePure to prepare for side effect check.

Use cloneTreePure when what is being cloned must be side-effect free.
Use cloneTree when safe to contain side effects (e.g. cloning module).
This commit is contained in:
Wilson Snyder 2023-09-16 22:50:54 -04:00
parent cd1fe64e6c
commit 761adf1cf0
25 changed files with 193 additions and 180 deletions

View File

@ -243,7 +243,7 @@ private:
} }
// Build a bitmask of the true predicates // Build a bitmask of the true predicates
AstNodeExpr* const predp = ifp->condp()->cloneTree(false); AstNodeExpr* const predp = ifp->condp()->cloneTreePure(false);
if (propp) { if (propp) {
propp = new AstConcat{nodep->fileline(), predp, propp}; propp = new AstConcat{nodep->fileline(), predp, propp};
} else { } else {
@ -312,17 +312,17 @@ private:
icondp = VN_AS(icondp->nextp(), NodeExpr)) { icondp = VN_AS(icondp->nextp(), NodeExpr)) {
AstNodeExpr* onep; AstNodeExpr* onep;
if (AstInsideRange* const rcondp = VN_CAST(icondp, InsideRange)) { if (AstInsideRange* const rcondp = VN_CAST(icondp, InsideRange)) {
onep = rcondp->newAndFromInside(nodep->exprp(), onep = rcondp->newAndFromInside(
rcondp->lhsp()->cloneTree(true), nodep->exprp(), rcondp->lhsp()->cloneTreePure(true),
rcondp->rhsp()->cloneTree(true)); rcondp->rhsp()->cloneTreePure(true));
} else if (nodep->casex() || nodep->casez() || nodep->caseInside()) { } else if (nodep->casex() || nodep->casez() || nodep->caseInside()) {
onep = AstEqWild::newTyped(itemp->fileline(), onep = AstEqWild::newTyped(itemp->fileline(),
nodep->exprp()->cloneTree(false), nodep->exprp()->cloneTreePure(false),
icondp->cloneTree(false)); icondp->cloneTreePure(false));
} else { } else {
onep = AstEq::newTyped(icondp->fileline(), onep = AstEq::newTyped(icondp->fileline(),
nodep->exprp()->cloneTree(false), nodep->exprp()->cloneTreePure(false),
icondp->cloneTree(false)); icondp->cloneTreePure(false));
} }
if (propp) { if (propp) {
propp = new AstConcat{icondp->fileline(), onep, propp}; propp = new AstConcat{icondp->fileline(), onep, propp};

View File

@ -177,7 +177,7 @@ private:
if (nodep->direction() == VDirection::OUTPUT) { if (nodep->direction() == VDirection::OUTPUT) {
AstVarRef* const skewedRefp = new AstVarRef{flp, varp, VAccess::READ}; AstVarRef* const skewedRefp = new AstVarRef{flp, varp, VAccess::READ};
skewedRefp->user1(true); 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()) { if (skewp->isZero()) {
// Drive the var in Re-NBA (IEEE 1800-2017 14.16) // Drive the var in Re-NBA (IEEE 1800-2017 14.16)
m_clockingp->addNextHere(new AstAlwaysReactive{ m_clockingp->addNextHere(new AstAlwaysReactive{
@ -208,12 +208,12 @@ private:
refp->user1(true); refp->user1(true);
if (skewp->num().is1Step()) { if (skewp->num().is1Step()) {
// Assign the sampled expression to the clockvar (IEEE 1800-2017 14.13) // 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); sampledp->dtypeFrom(exprp);
m_clockingp->addNextHere(new AstAssignW{flp, refp, sampledp}); m_clockingp->addNextHere(new AstAssignW{flp, refp, sampledp});
} else if (skewp->isZero()) { } else if (skewp->isZero()) {
// #0 means the var has to be sampled in Observed (IEEE 1800-2017 14.13) // #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{ m_clockingp->addNextHere(new AstAlwaysObserved{
flp, new AstSenTree{flp, m_clockingp->sensesp()->cloneTree(false)}, assignp}); flp, new AstSenTree{flp, m_clockingp->sensesp()->cloneTree(false)}, assignp});
} else { } else {
@ -230,7 +230,7 @@ private:
AstCMethodHard* const pushp = new AstCMethodHard{ AstCMethodHard* const pushp = new AstCMethodHard{
flp, new AstVarRef{flp, queueVarp, VAccess::WRITE}, "push", flp, new AstVarRef{flp, queueVarp, VAccess::WRITE}, "push",
new AstTime{nodep->fileline(), m_modp->timeunit()}}; new AstTime{nodep->fileline(), m_modp->timeunit()}};
pushp->addPinsp(exprp->cloneTree(false)); pushp->addPinsp(exprp->cloneTreePure(false));
pushp->dtypeSetVoid(); pushp->dtypeSetVoid();
m_clockingp->addNextHere( m_clockingp->addNextHere(
new AstAlways{flp, VAlwaysKwd::ALWAYS, nullptr, pushp->makeStmt()}); new AstAlways{flp, VAlwaysKwd::ALWAYS, nullptr, pushp->makeStmt()});
@ -372,7 +372,7 @@ private:
if (sentreep) sentreep->unlinkFrBack(); if (sentreep) sentreep->unlinkFrBack();
AstNodeExpr* const past = new AstPast{fl, exprp, nullptr}; AstNodeExpr* const past = new AstPast{fl, exprp, nullptr};
past->dtypeFrom(exprp); 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(); exprp->dtypeSetBit();
nodep->replaceWith(exprp); nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep, sentreep)); nodep->sentreep(newSenTree(nodep, sentreep));
@ -393,7 +393,7 @@ private:
if (sentreep) sentreep->unlinkFrBack(); if (sentreep) sentreep->unlinkFrBack();
AstNodeExpr* const past = new AstPast{fl, exprp, nullptr}; AstNodeExpr* const past = new AstPast{fl, exprp, nullptr};
past->dtypeFrom(exprp); 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(); exprp->dtypeSetBit();
nodep->replaceWith(exprp); nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep, sentreep)); nodep->sentreep(newSenTree(nodep, sentreep));
@ -408,7 +408,7 @@ private:
if (sentreep) sentreep->unlinkFrBack(); if (sentreep) sentreep->unlinkFrBack();
AstNodeExpr* const past = new AstPast{fl, exprp, nullptr}; AstNodeExpr* const past = new AstPast{fl, exprp, nullptr};
past->dtypeFrom(exprp); past->dtypeFrom(exprp);
exprp = new AstEq{fl, past, exprp->cloneTree(false)}; exprp = new AstEq{fl, past, exprp->cloneTreePure(false)};
exprp->dtypeSetBit(); exprp->dtypeSetBit();
nodep->replaceWith(exprp); nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep, sentreep)); nodep->sentreep(newSenTree(nodep, sentreep));
@ -442,7 +442,7 @@ private:
// Block is the new expression to evaluate // Block is the new expression to evaluate
AstNodeExpr* blockp = VN_AS(nodep->propp()->unlinkFrBack(), NodeExpr); AstNodeExpr* blockp = VN_AS(nodep->propp()->unlinkFrBack(), NodeExpr);
if (AstNodeExpr* const disablep = nodep->disablep()) { if (AstNodeExpr* const disablep = nodep->disablep()) {
m_disablep = disablep->cloneTree(false); m_disablep = disablep->cloneTreePure(false);
if (VN_IS(nodep->backp(), Cover)) { if (VN_IS(nodep->backp(), Cover)) {
blockp = new AstAnd{disablep->fileline(), blockp = new AstAnd{disablep->fileline(),
new AstNot{disablep->fileline(), disablep->unlinkFrBack()}, new AstNot{disablep->fileline(), disablep->unlinkFrBack()},

View File

@ -1998,7 +1998,8 @@ public:
AstNode* belowp); // When calling, "this" is second argument AstNode* belowp); // When calling, "this" is second argument
// METHODS - Iterate on a tree // 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? bool gateTree() { return gateTreeIter(); } // Is tree isGateOptimizable?
inline bool sameTree(const AstNode* node2p) const; // Does tree of this == node2p? inline bool sameTree(const AstNode* node2p) const; // Does tree of this == node2p?
// Does tree of this == node2p?, not allowing non-isGateOptimizable // Does tree of this == node2p?, not allowing non-isGateOptimizable

View File

@ -4187,10 +4187,10 @@ class AstCountBits final : public AstNodeQuadop {
// Number of bits set in vector // Number of bits set in vector
public: public:
AstCountBits(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ctrl1p) AstCountBits(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ctrl1p)
: ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl1p->cloneTree(false), : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl1p->cloneTreePure(false),
ctrl1p->cloneTree(false)) {} ctrl1p->cloneTreePure(false)) {}
AstCountBits(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ctrl1p, AstNodeExpr* ctrl2p) 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, AstCountBits(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ctrl1p, AstNodeExpr* ctrl2p,
AstNodeExpr* ctrl3p) AstNodeExpr* ctrl3p)
: ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {} : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {}

View File

@ -279,8 +279,8 @@ AstExecGraph::~AstExecGraph() { VL_DO_DANGLING(delete m_depGraphp, m_depGraphp);
AstNodeExpr* AstInsideRange::newAndFromInside(AstNodeExpr* exprp, AstNodeExpr* lhsp, AstNodeExpr* AstInsideRange::newAndFromInside(AstNodeExpr* exprp, AstNodeExpr* lhsp,
AstNodeExpr* rhsp) { AstNodeExpr* rhsp) {
AstNodeExpr* const ap = new AstGte{fileline(), exprp->cloneTree(true), lhsp}; AstNodeExpr* const ap = new AstGte{fileline(), exprp->cloneTreePure(true), lhsp};
AstNodeExpr* const bp = new AstLte{fileline(), exprp->cloneTree(true), rhsp}; AstNodeExpr* const bp = new AstLte{fileline(), exprp->cloneTreePure(true), rhsp};
ap->fileline()->modifyWarnOff(V3ErrorCode::UNSIGNED, true); ap->fileline()->modifyWarnOff(V3ErrorCode::UNSIGNED, true);
bp->fileline()->modifyWarnOff(V3ErrorCode::CMPCONST, true); bp->fileline()->modifyWarnOff(V3ErrorCode::CMPCONST, true);
return new AstAnd{fileline(), ap, bp}; return new AstAnd{fileline(), ap, bp};

View File

@ -362,10 +362,10 @@ private:
// Alternate scheme if we ever do multiple bits at a time: // Alternate scheme if we ever do multiple bits at a time:
// V3Number nummask (cexprp, cexprp->width(), (1UL<<msb)); // 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)); // new AstConst(cexprp->fileline(), nummask));
AstNodeExpr* const and1p AstNodeExpr* const and1p
= new AstSel{cexprp->fileline(), cexprp->cloneTree(false), msb, 1}; = new AstSel{cexprp->fileline(), cexprp->cloneTreePure(false), msb, 1};
AstNodeExpr* const eqp AstNodeExpr* const eqp
= new AstNeq{cexprp->fileline(), new AstConst{cexprp->fileline(), 0}, and1p}; = new AstNeq{cexprp->fileline(), new AstConst{cexprp->fileline(), 0}, and1p};
AstIf* const ifp = new AstIf{cexprp->fileline(), eqp, tree1p, tree0p}; AstIf* const ifp = new AstIf{cexprp->fileline(), eqp, tree1p, tree0p};
@ -450,7 +450,7 @@ private:
V3Number numval{itemp, iconstp->width()}; V3Number numval{itemp, iconstp->width()};
numval.opBitsOne(iconstp->num()); numval.opBitsOne(iconstp->num());
AstNodeExpr* const and1p AstNodeExpr* const and1p
= new AstAnd{itemp->fileline(), cexprp->cloneTree(false), = new AstAnd{itemp->fileline(), cexprp->cloneTreePure(false),
new AstConst{itemp->fileline(), nummask}}; new AstConst{itemp->fileline(), nummask}};
AstNodeExpr* const and2p = new AstAnd{ AstNodeExpr* const and2p = new AstAnd{
itemp->fileline(), new AstConst{itemp->fileline(), numval}, itemp->fileline(), new AstConst{itemp->fileline(), numval},
@ -460,7 +460,7 @@ private:
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p); condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
} else { } else {
// Not a caseX mask, we can build CASEEQ(cexpr icond) // 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; AstNodeExpr* const and2p = icondp;
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p); condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
} }
@ -502,7 +502,7 @@ private:
if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1; if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1;
if (depth == 1) { // First group or starting new group if (depth == 1) { // First group or starting new group
itemnextp = nullptr; itemnextp = nullptr;
AstIf* const newp = new AstIf{itemp->fileline(), ifexprp->cloneTree(true)}; AstIf* const newp = new AstIf{itemp->fileline(), ifexprp->cloneTreePure(true)};
if (groupnextp) { if (groupnextp) {
groupnextp->addElsesp(newp); groupnextp->addElsesp(newp);
} else { } else {
@ -512,7 +512,7 @@ private:
} else { // Continue group, modify if condition to OR in this new condition } else { // Continue group, modify if condition to OR in this new condition
AstNodeExpr* const condp = groupnextp->condp()->unlinkFrBack(); AstNodeExpr* const condp = groupnextp->condp()->unlinkFrBack();
groupnextp->condp( 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 { // Make the new lower IF and attach in the tree

View File

@ -1494,13 +1494,13 @@ private:
const AstSel* rselp = VN_CAST(rhsp, Sel); const AstSel* rselp = VN_CAST(rhsp, Sel);
// a[i:0] a // a[i:0] a
if (lselp && !rselp && rhsp->sameGateTree(lselp->fromp())) 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} // a[i:j] {a[j-1:k], b}
if (lselp && !rselp && VN_IS(rhsp, Concat)) if (lselp && !rselp && VN_IS(rhsp, Concat))
return ifMergeAdjacent(lhsp, VN_CAST(rhsp, Concat)->lhsp()); return ifMergeAdjacent(lhsp, VN_CAST(rhsp, Concat)->lhsp());
// a a[msb:j] // a a[msb:j]
if (rselp && !lselp && lhsp->sameGateTree(rselp->fromp())) 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] // {b, a[j:k]} a[k-1:i]
if (rselp && !lselp && VN_IS(lhsp, Concat)) if (rselp && !lselp && VN_IS(lhsp, Concat))
return ifMergeAdjacent(VN_CAST(lhsp, Concat)->rhsp(), rhsp); return ifMergeAdjacent(VN_CAST(lhsp, Concat)->rhsp(), rhsp);
@ -1812,10 +1812,10 @@ private:
// {llp OP lrp, rlp OP rrp} => {llp, rlp} OP {lrp, rrp}, where OP = AND/OR/XOR // {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 lp = VN_AS(nodep->lhsp(), NodeBiop);
AstNodeBiop* const rp = VN_AS(nodep->rhsp(), NodeBiop); AstNodeBiop* const rp = VN_AS(nodep->rhsp(), NodeBiop);
AstNodeExpr* const llp = lp->lhsp()->cloneTree(false); AstNodeExpr* const llp = lp->lhsp()->cloneTreePure(false);
AstNodeExpr* const lrp = lp->rhsp()->cloneTree(false); AstNodeExpr* const lrp = lp->rhsp()->cloneTreePure(false);
AstNodeExpr* const rlp = rp->lhsp()->cloneTree(false); AstNodeExpr* const rlp = rp->lhsp()->cloneTreePure(false);
AstNodeExpr* const rrp = rp->rhsp()->cloneTree(false); AstNodeExpr* const rrp = rp->rhsp()->cloneTreePure(false);
if (concatMergeable(lp, rp, 0)) { if (concatMergeable(lp, rp, 0)) {
AstConcat* const newlp = new AstConcat{rlp->fileline(), llp, rlp}; AstConcat* const newlp = new AstConcat{rlp->fileline(), llp, rlp};
AstConcat* const newrp = new AstConcat{rrp->fileline(), lrp, rrp}; AstConcat* const newrp = new AstConcat{rrp->fileline(), lrp, rrp};
@ -1897,9 +1897,9 @@ private:
AstNodeExpr* const ap = lhsp->lhsp()->unlinkFrBack(); AstNodeExpr* const ap = lhsp->lhsp()->unlinkFrBack();
AstNodeExpr* const bp = lhsp->rhsp()->unlinkFrBack(); AstNodeExpr* const bp = lhsp->rhsp()->unlinkFrBack();
AstNodeBiop* const shift1p = nodep; AstNodeBiop* const shift1p = nodep;
AstNodeBiop* const shift2p = nodep->cloneTree(true); AstNodeBiop* const shift2p = nodep->cloneTreePure(true);
shift1p->lhsp(ap); shift1p->lhsp(ap);
shift1p->rhsp(shiftp->cloneTree(true)); shift1p->rhsp(shiftp->cloneTreePure(true));
shift2p->lhsp(bp); shift2p->lhsp(bp);
shift2p->rhsp(shiftp); shift2p->rhsp(shiftp);
AstNodeBiop* const newp = lhsp; AstNodeBiop* const newp = lhsp;
@ -2085,7 +2085,7 @@ private:
AstNodeExpr* const lc2p = VN_AS(nodep->lhsp(), Concat)->rhsp()->unlinkFrBack(); AstNodeExpr* const lc2p = VN_AS(nodep->lhsp(), Concat)->rhsp()->unlinkFrBack();
AstNodeExpr* const conp = VN_AS(nodep->lhsp(), Concat)->unlinkFrBack(); AstNodeExpr* const conp = VN_AS(nodep->lhsp(), Concat)->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack(); AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const rhs2p = rhsp->cloneTree(false); AstNodeExpr* const rhs2p = rhsp->cloneTreePure(false);
// Calc widths // Calc widths
const int lsb2 = 0; const int lsb2 = 0;
const int msb2 = lsb2 + lc2p->width() - 1; const int msb2 = lsb2 + lc2p->width() - 1;
@ -2430,8 +2430,8 @@ private:
nodep->fileline(), nodep->fileline(),
new AstLogOr{nodep->fileline(), new AstLogNot{nodep->fileline(), lhsp}, rhsp}, new AstLogOr{nodep->fileline(), new AstLogNot{nodep->fileline(), lhsp}, rhsp},
new AstLogOr{nodep->fileline(), new AstLogOr{nodep->fileline(),
new AstLogNot{nodep->fileline(), rhsp->cloneTree(false)}, new AstLogNot{nodep->fileline(), rhsp->cloneTreePure(false)},
lhsp->cloneTree(false)}}; lhsp->cloneTreePure(false)}};
newp->dtypeFrom(nodep); newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep); VL_DO_DANGLING(nodep->deleteTree(), nodep);
@ -2588,8 +2588,8 @@ private:
AstNodeExpr* const bilhsp = fromp->lhsp()->unlinkFrBack(); AstNodeExpr* const bilhsp = fromp->lhsp()->unlinkFrBack();
AstNodeExpr* const birhsp = fromp->rhsp()->unlinkFrBack(); AstNodeExpr* const birhsp = fromp->rhsp()->unlinkFrBack();
// //
fromp->lhsp( fromp->lhsp(new AstSel{nodep->fileline(), bilhsp, lsbp->cloneTreePure(true),
new AstSel{nodep->fileline(), bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)}); widthp->cloneTreePure(true)});
fromp->rhsp(new AstSel{nodep->fileline(), birhsp, lsbp, widthp}); fromp->rhsp(new AstSel{nodep->fileline(), birhsp, lsbp, widthp});
fromp->dtypeFrom(nodep); fromp->dtypeFrom(nodep);
nodep->replaceWith(fromp); nodep->replaceWith(fromp);

View File

@ -353,7 +353,7 @@ private:
} }
if (bitselp) { if (bitselp) {
selectsp = new AstSel{nodep->fileline(), selectsp, bitreadp, selectsp = new AstSel{nodep->fileline(), selectsp, bitreadp,
bitselp->widthp()->cloneTree(false)}; bitselp->widthp()->cloneTreePure(false)}; // Always pure
} }
// Build "IF (changeit) ... // Build "IF (changeit) ...
UINFO(9, " For " << setvscp << endl); UINFO(9, " For " << setvscp << endl);

View File

@ -282,8 +282,8 @@ class DfgToAstVisitor final : DfgVisitor {
FileLine* const flp = dfgVarp->driverFileLine(idx); FileLine* const flp = dfgVarp->driverFileLine(idx);
AstConst* const lsbp = new AstConst{flp, dfgVarp->driverLsb(idx)}; AstConst* const lsbp = new AstConst{flp, dfgVarp->driverLsb(idx)};
AstConst* const widthp = new AstConst{flp, edge.sourcep()->width()}; AstConst* const widthp = new AstConst{flp, edge.sourcep()->width()};
AstSel* const rhsp = new AstSel{flp, rRef(), lsbp, widthp->cloneTree(false)}; AstSel* const rhsp = new AstSel{flp, rRef(), lsbp, widthp->cloneTreePure(false)};
AstSel* const lhsp = new AstSel{flp, wRef(), lsbp->cloneTree(false), widthp}; AstSel* const lhsp = new AstSel{flp, wRef(), lsbp->cloneTreePure(false), widthp};
// Add assignment of the value to the selected bits // Add assignment of the value to the selected bits
addResultEquation(flp, lhsp, rhsp); addResultEquation(flp, lhsp, rhsp);
}); });

View File

@ -137,7 +137,7 @@ private:
AstNodeExpr* rhsp) { AstNodeExpr* rhsp) {
FileLine* const fl = placep->fileline(); FileLine* const fl = placep->fileline();
return new AstAssign{fl, return new AstAssign{fl,
new AstWordSel{fl, lhsp->cloneTree(true), new AstWordSel{fl, lhsp->cloneTreePure(true),
new AstConst{fl, static_cast<uint32_t>(word)}}, new AstConst{fl, static_cast<uint32_t>(word)}},
rhsp}; rhsp};
} }
@ -166,20 +166,20 @@ private:
// Concat may pass negative word numbers, that means it wants a zero // Concat may pass negative word numbers, that means it wants a zero
FileLine* const fl = nodep->fileline(); FileLine* const fl = nodep->fileline();
if (nodep->isWide() && word >= 0 && word < nodep->widthWords()) { if (nodep->isWide() && word >= 0 && word < nodep->widthWords()) {
return new AstWordSel{fl, nodep->cloneTree(true), return new AstWordSel{fl, nodep->cloneTreePure(true),
new AstConst{fl, static_cast<uint32_t>(word)}}; new AstConst{fl, static_cast<uint32_t>(word)}};
} else if (nodep->isQuad() && word == 0) { } else if (nodep->isQuad() && word == 0) {
AstNodeExpr* const quadfromp = nodep->cloneTree(true); AstNodeExpr* const quadfromp = nodep->cloneTreePure(true);
quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(), VSigning::UNSIGNED); quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(), VSigning::UNSIGNED);
return new AstCCast{fl, quadfromp, VL_EDATASIZE}; return new AstCCast{fl, quadfromp, VL_EDATASIZE};
} else if (nodep->isQuad() && word == 1) { } else if (nodep->isQuad() && word == 1) {
AstNodeExpr* const quadfromp = nodep->cloneTree(true); AstNodeExpr* const quadfromp = nodep->cloneTreePure(true);
quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(), VSigning::UNSIGNED); quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(), VSigning::UNSIGNED);
return new AstCCast{ return new AstCCast{
fl, new AstShiftR{fl, quadfromp, new AstConst{fl, VL_EDATASIZE}, VL_EDATASIZE}, fl, new AstShiftR{fl, quadfromp, new AstConst{fl, VL_EDATASIZE}, VL_EDATASIZE},
VL_EDATASIZE}; VL_EDATASIZE};
} else if (!nodep->isWide() && !nodep->isQuad() && word == 0) { } else if (!nodep->isWide() && !nodep->isQuad() && word == 0) {
return nodep->cloneTree(true); return nodep->cloneTreePure(true);
} else { // Out of bounds } else { // Out of bounds
return new AstConst{fl, 0}; return new AstConst{fl, 0};
} }
@ -231,7 +231,7 @@ private:
if (VN_IS(lsbp, Const)) { if (VN_IS(lsbp, Const)) {
wordp = new AstConst{lfl, wordOffset + VL_BITWORD_E(VN_AS(lsbp, Const)->toUInt())}; wordp = new AstConst{lfl, wordOffset + VL_BITWORD_E(VN_AS(lsbp, Const)->toUInt())};
} else { } else {
wordp = new AstShiftR{lfl, lsbp->cloneTree(true), wordp = new AstShiftR{lfl, lsbp->cloneTreePure(true),
new AstConst{lfl, VL_EDATASIZE_LOG2}, VL_EDATASIZE}; new AstConst{lfl, VL_EDATASIZE_LOG2}, VL_EDATASIZE};
if (wordOffset if (wordOffset
!= 0) { // This is indexing a arraysel, so a 32 bit constant is fine != 0) { // This is indexing a arraysel, so a 32 bit constant is fine
@ -260,7 +260,7 @@ private:
return new AstConst{fl, VL_BITBIT_E(VN_AS(lsbp, Const)->toUInt())}; return new AstConst{fl, VL_BITBIT_E(VN_AS(lsbp, Const)->toUInt())};
} else { } else {
return new AstAnd{fl, new AstConst{fl, VL_EDATASIZE - 1}, return new AstAnd{fl, new AstConst{fl, VL_EDATASIZE - 1},
dropCondBound(lsbp)->cloneTree(true)}; dropCondBound(lsbp)->cloneTreePure(true)};
} }
} }
@ -351,7 +351,7 @@ private:
FileLine* const fl = nodep->fileline(); FileLine* const fl = nodep->fileline();
for (int w = 0; w < nodep->widthWords(); ++w) { for (int w = 0; w < nodep->widthWords(); ++w) {
addWordAssign(nodep, w, addWordAssign(nodep, w,
new AstCond{fl, rhsp->condp()->cloneTree(true), new AstCond{fl, rhsp->condp()->cloneTreePure(true),
newAstWordSelClone(rhsp->thenp(), w), newAstWordSelClone(rhsp->thenp(), w),
newAstWordSelClone(rhsp->elsep(), w)}); newAstWordSelClone(rhsp->elsep(), w)});
} }
@ -419,7 +419,7 @@ private:
FileLine* const lfl = nodep->lsbp()->fileline(); FileLine* const lfl = nodep->lsbp()->fileline();
FileLine* const ffl = nodep->fromp()->fileline(); FileLine* const ffl = nodep->fromp()->fileline();
AstNodeExpr* lowwordp AstNodeExpr* lowwordp
= newWordSel(ffl, nodep->fromp()->cloneTree(true), nodep->lsbp()); = newWordSel(ffl, nodep->fromp()->cloneTreePure(true), nodep->lsbp());
if (nodep->isQuad() && !lowwordp->isQuad()) { if (nodep->isQuad() && !lowwordp->isQuad()) {
lowwordp = new AstCCast{nfl, lowwordp, nodep}; lowwordp = new AstCCast{nfl, lowwordp, nodep};
} }
@ -431,9 +431,9 @@ private:
const uint32_t midMsbOffset const uint32_t midMsbOffset
= std::min<uint32_t>(nodep->widthConst(), VL_EDATASIZE) - 1; = std::min<uint32_t>(nodep->widthConst(), VL_EDATASIZE) - 1;
AstNodeExpr* const midMsbp = new AstAdd{lfl, new AstConst{lfl, midMsbOffset}, AstNodeExpr* const midMsbp = new AstAdd{lfl, new AstConst{lfl, midMsbOffset},
nodep->lsbp()->cloneTree(true)}; nodep->lsbp()->cloneTreePure(true)};
AstNodeExpr* midwordp = // SEL(from,[midwordnum]) AstNodeExpr* midwordp = // SEL(from,[midwordnum])
newWordSel(ffl, nodep->fromp()->cloneTree(true), midMsbp, 0); newWordSel(ffl, nodep->fromp()->cloneTreePure(true), midMsbp, 0);
// newWordSel clones the index, so delete it // newWordSel clones the index, so delete it
VL_DO_DANGLING(midMsbp->deleteTree(), midMsbp); VL_DO_DANGLING(midMsbp->deleteTree(), midMsbp);
if (nodep->isQuad() && !midwordp->isQuad()) { if (nodep->isQuad() && !midwordp->isQuad()) {
@ -459,9 +459,9 @@ private:
if (nodep->widthConst() > VL_EDATASIZE) { if (nodep->widthConst() > VL_EDATASIZE) {
const uint32_t hiMsbOffset = nodep->widthConst() - 1; const uint32_t hiMsbOffset = nodep->widthConst() - 1;
AstNodeExpr* const hiMsbp = new AstAdd{lfl, new AstConst{lfl, hiMsbOffset}, AstNodeExpr* const hiMsbp = new AstAdd{lfl, new AstConst{lfl, hiMsbOffset},
nodep->lsbp()->cloneTree(true)}; nodep->lsbp()->cloneTreePure(true)};
AstNodeExpr* hiwordp = // SEL(from,[hiwordnum]) AstNodeExpr* hiwordp = // SEL(from,[hiwordnum])
newWordSel(ffl, nodep->fromp()->cloneTree(true), hiMsbp); newWordSel(ffl, nodep->fromp()->cloneTreePure(true), hiMsbp);
// newWordSel clones the index, so delete it // newWordSel clones the index, so delete it
VL_DO_DANGLING(hiMsbp->deleteTree(), hiMsbp); VL_DO_DANGLING(hiMsbp->deleteTree(), hiMsbp);
if (nodep->isQuad() && !hiwordp->isQuad()) { if (nodep->isQuad() && !hiwordp->isQuad()) {
@ -518,13 +518,13 @@ private:
for (int w = 0; w < nodep->widthWords(); ++w) { for (int w = 0; w < nodep->widthWords(); ++w) {
// Grab lowest bits // Grab lowest bits
AstNodeExpr* const lowwordp AstNodeExpr* const lowwordp
= newWordSel(rfl, rhsp->fromp()->cloneTree(true), rhsp->lsbp(), w); = newWordSel(rfl, rhsp->fromp()->cloneTreePure(true), rhsp->lsbp(), w);
AstNodeExpr* const lowp AstNodeExpr* const lowp
= new AstShiftR{rfl, lowwordp, newSelBitBit(rhsp->lsbp()), VL_EDATASIZE}; = new AstShiftR{rfl, lowwordp, newSelBitBit(rhsp->lsbp()), VL_EDATASIZE};
// Upper bits // Upper bits
const V3Number zero{nodep, VL_EDATASIZE, 0}; const V3Number zero{nodep, VL_EDATASIZE, 0};
AstNodeExpr* const midwordp = // SEL(from,[1+wordnum]) AstNodeExpr* const midwordp = // SEL(from,[1+wordnum])
newWordSel(ffl, rhsp->fromp()->cloneTree(true), rhsp->lsbp(), w + 1); newWordSel(ffl, rhsp->fromp()->cloneTreePure(true), rhsp->lsbp(), w + 1);
AstNodeExpr* const midshiftp AstNodeExpr* const midshiftp
= new AstSub{lfl, new AstConst{lfl, VL_EDATASIZE}, newSelBitBit(rhsp->lsbp())}; = new AstSub{lfl, new AstConst{lfl, VL_EDATASIZE}, newSelBitBit(rhsp->lsbp())};
AstNodeExpr* const midmayp = new AstShiftL{rfl, midwordp, midshiftp, VL_EDATASIZE}; AstNodeExpr* const midmayp = new AstShiftL{rfl, midwordp, midshiftp, VL_EDATASIZE};
@ -596,9 +596,9 @@ private:
} else { } else {
UINFO(8, " ASSIGNSEL(const,narrow) " << nodep << endl); UINFO(8, " ASSIGNSEL(const,narrow) " << nodep << endl);
if (destp->isQuad() && !rhsp->isQuad()) { rhsp = new AstCCast{nfl, rhsp, nodep}; } if (destp->isQuad() && !rhsp->isQuad()) { rhsp = new AstCCast{nfl, rhsp, nodep}; }
AstNodeExpr* oldvalp = destp->cloneTree(true); AstNodeExpr* oldvalp = destp->cloneTreePure(true);
fixCloneLvalue(oldvalp); fixCloneLvalue(oldvalp);
if (!ones) { oldvalp = new AstAnd{lfl, new AstConst{lfl, maskold}, oldvalp}; } if (!ones) oldvalp = new AstAnd{lfl, new AstConst{lfl, maskold}, oldvalp};
// The bit-select can refer to bits outside the width of nodep // The bit-select can refer to bits outside the width of nodep
// which we aren't allowed to assign to. This is a mask of the // which we aren't allowed to assign to. This is a mask of the
@ -619,7 +619,7 @@ private:
UINFO(8, " ASSIGNSEL(varlsb,wide,1bit) " << nodep << endl); UINFO(8, " ASSIGNSEL(varlsb,wide,1bit) " << nodep << endl);
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack(); AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const destp = lhsp->fromp()->unlinkFrBack(); AstNodeExpr* const destp = lhsp->fromp()->unlinkFrBack();
AstNodeExpr* oldvalp = newWordSel(lfl, destp->cloneTree(true), lhsp->lsbp()); AstNodeExpr* oldvalp = newWordSel(lfl, destp->cloneTreePure(true), lhsp->lsbp());
fixCloneLvalue(oldvalp); fixCloneLvalue(oldvalp);
if (!ones) { if (!ones) {
oldvalp = new AstAnd{ oldvalp = new AstAnd{
@ -633,7 +633,7 @@ private:
oldvalp}; oldvalp};
} }
// Restrict the shift amount to 0-31, see bug804. // Restrict the shift amount to 0-31, see bug804.
AstNodeExpr* const shiftp = new AstAnd{nfl, lhsp->lsbp()->cloneTree(true), AstNodeExpr* const shiftp = new AstAnd{nfl, lhsp->lsbp()->cloneTreePure(true),
new AstConst{nfl, VL_EDATASIZE - 1}}; new AstConst{nfl, VL_EDATASIZE - 1}};
AstNode* const newp = new AstAssign{ AstNode* const newp = new AstAssign{
nfl, newWordSel(nfl, destp, lhsp->lsbp()), nfl, newWordSel(nfl, destp, lhsp->lsbp()),
@ -657,7 +657,7 @@ private:
// nodep->dumpTree("- old: "); // nodep->dumpTree("- old: ");
AstNodeExpr* rhsp = nodep->rhsp()->unlinkFrBack(); AstNodeExpr* rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const destp = lhsp->fromp()->unlinkFrBack(); AstNodeExpr* const destp = lhsp->fromp()->unlinkFrBack();
AstNodeExpr* oldvalp = destp->cloneTree(true); AstNodeExpr* oldvalp = destp->cloneTreePure(true);
fixCloneLvalue(oldvalp); fixCloneLvalue(oldvalp);
V3Number maskwidth{nodep, destp->widthMin()}; V3Number maskwidth{nodep, destp->widthMin()};
@ -667,13 +667,13 @@ private:
if (!ones) { if (!ones) {
oldvalp = new AstAnd{ oldvalp = new AstAnd{
lfl, lfl,
new AstNot{lfl, new AstNot{lfl, new AstShiftL{lfl, new AstConst{nfl, maskwidth},
new AstShiftL{lfl, new AstConst{nfl, maskwidth}, lhsp->lsbp()->cloneTreePure(true),
lhsp->lsbp()->cloneTree(true), destp->width()}}, destp->width()}},
oldvalp}; oldvalp};
} }
AstNodeExpr* newp AstNodeExpr* newp
= new AstShiftL{lfl, rhsp, lhsp->lsbp()->cloneTree(true), destp->width()}; = new AstShiftL{lfl, rhsp, lhsp->lsbp()->cloneTreePure(true), destp->width()};
// Apply cleaning to the new value being inserted. Mask is // Apply cleaning to the new value being inserted. Mask is
// slightly wider than necessary to avoid an AND with all ones // slightly wider than necessary to avoid an AND with all ones
// being optimized out. No need to clean if destp is // being optimized out. No need to clean if destp is
@ -749,12 +749,12 @@ private:
"Replication value isn't a constant. Checked earlier!"); "Replication value isn't a constant. Checked earlier!");
const uint32_t times = constp->toUInt(); const uint32_t times = constp->toUInt();
if (nodep->isQuad() && !lhsp->isQuad()) { lhsp = new AstCCast{fl, lhsp, nodep}; } if (nodep->isQuad() && !lhsp->isQuad()) { lhsp = new AstCCast{fl, lhsp, nodep}; }
newp = lhsp->cloneTree(true); newp = lhsp->cloneTreePure(true);
for (unsigned repnum = 1; repnum < times; repnum++) { for (unsigned repnum = 1; repnum < times; repnum++) {
const int rhsshift = repnum * lhswidth; const int rhsshift = repnum * lhswidth;
newp = new AstOr{ newp = new AstOr{
fl, fl,
new AstShiftL{fl, lhsp->cloneTree(true), new AstShiftL{fl, lhsp->cloneTreePure(true),
new AstConst{fl, static_cast<uint32_t>(rhsshift)}, new AstConst{fl, static_cast<uint32_t>(rhsshift)},
nodep->width()}, nodep->width()},
newp}; newp};
@ -778,7 +778,7 @@ private:
for (int w = 0; w < rhsp->widthWords(); ++w) { for (int w = 0; w < rhsp->widthWords(); ++w) {
AstNodeExpr* newp; AstNodeExpr* newp;
if (lhswidth == 1) { if (lhswidth == 1) {
newp = new AstNegate{fl, lhsp->cloneTree(true)}; newp = new AstNegate{fl, lhsp->cloneTreePure(true)};
// Replicate always unsigned // Replicate always unsigned
newp->dtypeSetLogicSized(VL_EDATASIZE, VSigning::UNSIGNED); newp->dtypeSetLogicSized(VL_EDATASIZE, VSigning::UNSIGNED);
} else { } else {

View File

@ -188,13 +188,13 @@ class ForceConvertVisitor final : public VNVisitor {
V3Number ones{lhsp, isRangedDType(lhsp) ? lhsp->width() : 1}; V3Number ones{lhsp, isRangedDType(lhsp) ? lhsp->width() : 1};
ones.setAllBits1(); ones.setAllBits1();
AstAssign* const setEnp AstAssign* const setEnp
= new AstAssign{flp, lhsp->cloneTree(false), new AstConst{rhsp->fileline(), ones}}; = new AstAssign{flp, lhsp->cloneTreePure(false), new AstConst{rhsp->fileline(), ones}};
transformWritenVarScopes(setEnp->lhsp(), [this](AstVarScope* vscp) { transformWritenVarScopes(setEnp->lhsp(), [this](AstVarScope* vscp) {
return getForceComponents(vscp).m_enVscp; return getForceComponents(vscp).m_enVscp;
}); });
// Set corresponding value signals to the forced value // Set corresponding value signals to the forced value
AstAssign* const setValp AstAssign* const setValp
= new AstAssign{flp, lhsp->cloneTree(false), rhsp->cloneTree(false)}; = new AstAssign{flp, lhsp->cloneTreePure(false), rhsp->cloneTreePure(false)};
transformWritenVarScopes(setValp->lhsp(), [this](AstVarScope* vscp) { transformWritenVarScopes(setValp->lhsp(), [this](AstVarScope* vscp) {
return getForceComponents(vscp).m_valVscp; return getForceComponents(vscp).m_valVscp;
}); });
@ -223,7 +223,7 @@ class ForceConvertVisitor final : public VNVisitor {
V3Number zero{lhsp, isRangedDType(lhsp) ? lhsp->width() : 1}; V3Number zero{lhsp, isRangedDType(lhsp) ? lhsp->width() : 1};
zero.setAllBits0(); zero.setAllBits0();
AstAssign* const resetEnp AstAssign* const resetEnp
= new AstAssign{flp, lhsp->cloneTree(false), new AstConst{lhsp->fileline(), zero}}; = new AstAssign{flp, lhsp->cloneTreePure(false), new AstConst{lhsp->fileline(), zero}};
transformWritenVarScopes(resetEnp->lhsp(), [this](AstVarScope* vscp) { transformWritenVarScopes(resetEnp->lhsp(), [this](AstVarScope* vscp) {
return getForceComponents(vscp).m_enVscp; return getForceComponents(vscp).m_enVscp;
}); });
@ -235,7 +235,7 @@ class ForceConvertVisitor final : public VNVisitor {
FileLine* const fl_nowarn = new FileLine{flp}; FileLine* const fl_nowarn = new FileLine{flp};
fl_nowarn->warnOff(V3ErrorCode::BLKANDNBLK, true); fl_nowarn->warnOff(V3ErrorCode::BLKANDNBLK, true);
AstAssign* const resetRdp AstAssign* const resetRdp
= new AstAssign{fl_nowarn, lhsp->cloneTree(false), lhsp->unlinkFrBack()}; = new AstAssign{fl_nowarn, lhsp->cloneTreePure(false), lhsp->unlinkFrBack()};
// Replace write refs on the LHS // Replace write refs on the LHS
resetRdp->lhsp()->foreach([this](AstNodeVarRef* refp) { resetRdp->lhsp()->foreach([this](AstNodeVarRef* refp) {
if (refp->access() != VAccess::WRITE) return; if (refp->access() != VAccess::WRITE) return;

View File

@ -395,7 +395,7 @@ private:
void optimizeElimVar(AstVarScope* varscp, AstNode* substp, AstNode* consumerp) { void optimizeElimVar(AstVarScope* varscp, AstNode* substp, AstNode* consumerp) {
if (debug() >= 5) consumerp->dumpTree("- elimUsePre: "); if (debug() >= 5) consumerp->dumpTree("- elimUsePre: ");
if (!m_substitutions.tryGet(consumerp)) m_optimized.push_back(consumerp); if (!m_substitutions.tryGet(consumerp)) m_optimized.push_back(consumerp);
m_substitutions(consumerp).emplace(varscp, substp->cloneTree(false)); m_substitutions(consumerp).emplace(varscp, substp->cloneTreePure(false));
} }
void commitElimVar(AstNode* logicp) { void commitElimVar(AstNode* logicp) {
@ -1008,7 +1008,7 @@ static void eliminate(AstNode* logicp,
// Prevent an infinite loop... // Prevent an infinite loop...
substp, "Replacing node with itself; perhaps circular logic?"); substp, "Replacing node with itself; perhaps circular logic?");
// The replacement // The replacement
AstNode* const newp = substp->cloneTree(false); AstNode* const newp = substp->cloneTreePure(false);
// Which fileline() to use? If replacing with logic, an error/warning is likely to want // Which fileline() to use? If replacing with logic, an error/warning is likely to want
// to point to the logic IE what we're replacing with. However, a VARREF should point // to point to the logic IE what we're replacing with. However, a VARREF should point
// to the original as it's otherwise confusing to throw warnings that point to a PIN // to the original as it's otherwise confusing to throw warnings that point to a PIN
@ -1219,9 +1219,10 @@ private:
preselp->replaceWith(newselp); preselp->replaceWith(newselp);
VL_DO_DANGLING(preselp->deleteTree(), preselp); VL_DO_DANGLING(preselp->deleteTree(), preselp);
// create new rhs for pre assignment // create new rhs for pre assignment
AstNode* const newrhsp = new AstConcat{ AstNode* const newrhsp
m_assignp->rhsp()->fileline(), m_assignp->rhsp()->cloneTree(false), = new AstConcat{m_assignp->rhsp()->fileline(),
assignp->rhsp()->cloneTree(false)}; m_assignp->rhsp()->cloneTreePure(false),
assignp->rhsp()->cloneTreePure(false)};
AstNode* const oldrhsp = m_assignp->rhsp(); AstNode* const oldrhsp = m_assignp->rhsp();
oldrhsp->replaceWith(newrhsp); oldrhsp->replaceWith(newrhsp);
VL_DO_DANGLING(oldrhsp->deleteTree(), oldrhsp); VL_DO_DANGLING(oldrhsp->deleteTree(), oldrhsp);

View File

@ -283,9 +283,9 @@ private:
// Define what operation will we be doing // Define what operation will we be doing
AstNodeExpr* operp; AstNodeExpr* operp;
if (VN_IS(nodep, PostSub) || VN_IS(nodep, PreSub)) { if (VN_IS(nodep, PostSub) || VN_IS(nodep, PreSub)) {
operp = new AstSub{fl, readp->cloneTree(true), newconstp}; operp = new AstSub{fl, readp->cloneTreePure(true), newconstp};
} else { } else {
operp = new AstAdd{fl, readp->cloneTree(true), newconstp}; operp = new AstAdd{fl, readp->cloneTreePure(true), newconstp};
} }
if (VN_IS(nodep, PreAdd) || VN_IS(nodep, PreSub)) { if (VN_IS(nodep, PreAdd) || VN_IS(nodep, PreSub)) {
@ -301,7 +301,7 @@ private:
// PostAdd/PostSub operations // PostAdd/PostSub operations
// Assign the original variable to the temporary one // Assign the original variable to the temporary one
AstAssign* const assignp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, AstAssign* const assignp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
readp->cloneTree(true)}; readp->cloneTreePure(true)};
insertNextToStmt(nodep, assignp); insertNextToStmt(nodep, assignp);
// Increment the original variable by one // Increment the original variable by one
assignp->addNextHere(new AstAssign{fl, writep, operp}); assignp->addNextHere(new AstAssign{fl, writep, operp});

View File

@ -601,7 +601,7 @@ private:
if (condp == rhsp) return resp; if (condp == rhsp) return resp;
if (const AstAnd* const andp = VN_CAST(rhsp, And)) { if (const AstAnd* const andp = VN_CAST(rhsp, And)) {
UASSERT_OBJ(andp->rhsp() == condp, rhsp, "Should not try to fold this"); UASSERT_OBJ(andp->rhsp() == condp, rhsp, "Should not try to fold this");
return new AstAnd{andp->fileline(), andp->lhsp()->cloneTree(false), resp}; return new AstAnd{andp->fileline(), andp->lhsp()->cloneTreePure(false), resp};
} }
} else if (const AstAnd* const andp = VN_CAST(rhsp, And)) { } else if (const AstAnd* const andp = VN_CAST(rhsp, And)) {
if (andp->lhsp()->sameTree(m_mgCondp)) { if (andp->lhsp()->sameTree(m_mgCondp)) {
@ -655,7 +655,7 @@ private:
// We need a copy of the condition in the new equivalent 'if' statement, // We need a copy of the condition in the new equivalent 'if' statement,
// and we also need to keep track of it for comparisons later. // and we also need to keep track of it for comparisons later.
m_mgCondp = m_mgCondp->cloneTree(false); m_mgCondp = m_mgCondp->cloneTreePure(false);
// Create equivalent 'if' statement and insert it before the first node // Create equivalent 'if' statement and insert it before the first node
AstIf* const resultp = new AstIf{m_mgCondp->fileline(), m_mgCondp}; AstIf* const resultp = new AstIf{m_mgCondp->fileline(), m_mgCondp};
m_mgFirstp->addHereThisAsNext(resultp); m_mgFirstp->addHereThisAsNext(resultp);

View File

@ -257,7 +257,7 @@ private:
// Create equivalent of VL_SIGNONES_(node_width) // Create equivalent of VL_SIGNONES_(node_width)
constzerop = new AstNegate{ constzerop = new AstNegate{
nodep->fileline(), nodep->fileline(),
new AstShiftR{nodep->fileline(), nodep->lhsp()->cloneTree(false), new AstShiftR{nodep->fileline(), nodep->lhsp()->cloneTreePure(false),
new AstConst(nodep->fileline(), m1value), nodep->width()}}; new AstConst(nodep->fileline(), m1value), nodep->width()}};
} else { } else {
constzerop = new AstConst{nodep->fileline(), AstConst::WidthedValue{}, constzerop = new AstConst{nodep->fileline(), AstConst::WidthedValue{},
@ -269,10 +269,10 @@ private:
= new AstConst(nodep->fileline(), AstConst::WidthedValue{}, = new AstConst(nodep->fileline(), AstConst::WidthedValue{},
nodep->rhsp()->widthMin(), m1value); nodep->rhsp()->widthMin(), m1value);
constwidthp->dtypeFrom(nodep->rhsp()); // unsigned constwidthp->dtypeFrom(nodep->rhsp()); // unsigned
AstCond* const newp = new AstCond{ AstCond* const newp = new AstCond{nodep->fileline(),
nodep->fileline(), new AstGte{nodep->fileline(), constwidthp,
new AstGte{nodep->fileline(), constwidthp, nodep->rhsp()->cloneTree(false)}, nodep->rhsp()->cloneTreePure(false)},
nodep, constzerop}; nodep, constzerop};
replaceHandle.relink(newp); replaceHandle.relink(newp);
} }
} }
@ -370,7 +370,7 @@ private:
UINFO(4, "Autoflush " << nodep << endl); UINFO(4, "Autoflush " << nodep << endl);
nodep->addNextHere( nodep->addNextHere(
new AstFFlush{nodep->fileline(), new AstFFlush{nodep->fileline(),
nodep->filep() ? nodep->filep()->cloneTree(true) : nullptr}); nodep->filep() ? nodep->filep()->cloneTreePure(true) : nullptr});
} }
} }
} }

View File

@ -338,7 +338,7 @@ private:
= new AstIf{itemp->fileline(), = new AstIf{itemp->fileline(),
new AstLte{condp->fileline(), new AstLte{condp->fileline(),
new AstVarRef{condp->fileline(), randVarp, VAccess::READ}, new AstVarRef{condp->fileline(), randVarp, VAccess::READ},
sump->cloneTree(true)}, sump->cloneTreePure(true)},
stmtsp, nullptr}; stmtsp, nullptr};
ifsp->addElsesp(newifp); ifsp->addElsesp(newifp);
ifsp = newifp; ifsp = newifp;

View File

@ -98,10 +98,10 @@ class SliceVisitor final : public VNVisitor {
nodep->v3error("Array initialization has too few elements, need element " nodep->v3error("Array initialization has too few elements, need element "
<< offset); << offset);
} }
newp = itemp ? itemp->cloneTree(false) : new AstConst{nodep->fileline(), 0}; newp = itemp ? itemp->cloneTreePure(false) : new AstConst{nodep->fileline(), 0};
} else if (AstNodeCond* const snodep = VN_CAST(nodep, NodeCond)) { } else if (AstNodeCond* const snodep = VN_CAST(nodep, NodeCond)) {
UINFO(9, " cloneCond(" << elements << "," << offset << ") " << nodep << endl); UINFO(9, " cloneCond(" << elements << "," << offset << ") " << nodep << endl);
return snodep->cloneType(snodep->condp()->cloneTree(false), return snodep->cloneType(snodep->condp()->cloneTreePure(false),
cloneAndSel(snodep->thenp(), elements, offset), cloneAndSel(snodep->thenp(), elements, offset),
cloneAndSel(snodep->elsep(), elements, offset)); cloneAndSel(snodep->elsep(), elements, offset));
} else if (const AstSliceSel* const snodep = VN_CAST(nodep, SliceSel)) { } else if (const AstSliceSel* const snodep = VN_CAST(nodep, SliceSel)) {
@ -110,7 +110,8 @@ class SliceVisitor final : public VNVisitor {
+ (!snodep->declRange().ascending() + (!snodep->declRange().ascending()
? snodep->declRange().elements() - 1 - offset ? snodep->declRange().elements() - 1 - offset
: offset)); : offset));
newp = new AstArraySel{nodep->fileline(), snodep->fromp()->cloneTree(false), leOffset}; newp = new AstArraySel{nodep->fileline(), snodep->fromp()->cloneTreePure(false),
leOffset};
} else if (VN_IS(nodep, ArraySel) || VN_IS(nodep, NodeVarRef) || VN_IS(nodep, NodeSel) } else if (VN_IS(nodep, ArraySel) || VN_IS(nodep, NodeVarRef) || VN_IS(nodep, NodeSel)
|| VN_IS(nodep, CMethodHard) || VN_IS(nodep, MemberSel) || VN_IS(nodep, CMethodHard) || VN_IS(nodep, MemberSel)
|| VN_IS(nodep, ExprStmt)) { || VN_IS(nodep, ExprStmt)) {
@ -118,7 +119,7 @@ class SliceVisitor final : public VNVisitor {
const int leOffset = !arrayp->rangep()->ascending() const int leOffset = !arrayp->rangep()->ascending()
? arrayp->rangep()->elementsConst() - 1 - offset ? arrayp->rangep()->elementsConst() - 1 - offset
: offset; : offset;
newp = new AstArraySel{nodep->fileline(), VN_AS(nodep, NodeExpr)->cloneTree(false), newp = new AstArraySel{nodep->fileline(), VN_AS(nodep, NodeExpr)->cloneTreePure(false),
leOffset}; leOffset};
} else { } else {
if (!m_assignError) { if (!m_assignError) {

View File

@ -767,6 +767,8 @@ protected:
// Clone this if into its set of split blocks // Clone this if into its set of split blocks
AstSplitPlaceholder* const if_placeholderp = makePlaceholderp(); AstSplitPlaceholder* const if_placeholderp = makePlaceholderp();
AstSplitPlaceholder* const else_placeholderp = makePlaceholderp(); AstSplitPlaceholder* const else_placeholderp = makePlaceholderp();
// We check for condition isPure earlier, but may still clone a
// non-pure to separate from other pure statements.
AstIf* const clonep = new AstIf{nodep->fileline(), nodep->condp()->cloneTree(true), AstIf* const clonep = new AstIf{nodep->fileline(), nodep->condp()->cloneTree(true),
if_placeholderp, else_placeholderp}; if_placeholderp, else_placeholderp};
const AstIf* const origp = VN_CAST(nodep, If); const AstIf* const origp = VN_CAST(nodep, If);

View File

@ -142,6 +142,9 @@ private:
void splitAlways(AstAlways* nodep, AstVarScope* splitVscp) { void splitAlways(AstAlways* nodep, AstVarScope* splitVscp) {
if (debug() >= 9) nodep->dumpTree("- in: "); if (debug() >= 9) nodep->dumpTree("- in: ");
// Duplicate it and link in // Duplicate it and link in
// Below cloneTree should perhaps be cloneTreePure, but given
// isolate_assignments is required to hit this code, we presume the user
// knows what they are asking for
AstAlways* const newp = nodep->cloneTree(false); AstAlways* const newp = nodep->cloneTree(false);
newp->user1(true); // So we don't clone it again newp->user1(true); // So we don't clone it again
nodep->addNextHere(newp); nodep->addNextHere(newp);

View File

@ -292,7 +292,7 @@ private:
} }
void replaceSubstEtc(AstNode* nodep, AstNodeExpr* substp) { void replaceSubstEtc(AstNode* nodep, AstNodeExpr* substp) {
if (debug() > 5) nodep->dumpTree("- substw_old: "); if (debug() > 5) nodep->dumpTree("- substw_old: ");
AstNodeExpr* newp = substp->cloneTree(true); AstNodeExpr* newp = substp->cloneTreePure(true);
if (!nodep->isQuad() && newp->isQuad()) { if (!nodep->isQuad() && newp->isQuad()) {
newp = new AstCCast{newp->fileline(), newp, nodep}; newp = new AstCCast{newp->fileline(), newp, nodep};
} }

View File

@ -516,14 +516,14 @@ class TristateVisitor final : public TristateBaseVisitor {
// Unlink lhsp before copying to save unnecessary copy of lhsp // Unlink lhsp before copying to save unnecessary copy of lhsp
AstNodeExpr* const lhsp = extendp->lhsp()->unlinkFrBack(); AstNodeExpr* const lhsp = extendp->lhsp()->unlinkFrBack();
AstExtend* const enExtendp = extendp->cloneTree(false); AstExtend* const enExtendp = extendp->cloneTreePure(false);
extendp->lhsp(lhsp); extendp->lhsp(lhsp);
AstNodeExpr* const enLhsp = getEnExprBasedOnOriginalp(lhsp); AstNodeExpr* const enLhsp = getEnExprBasedOnOriginalp(lhsp);
enExtendp->lhsp(new AstNot{enLhsp->fileline(), enLhsp}); enExtendp->lhsp(new AstNot{enLhsp->fileline(), enLhsp});
return new AstNot{enExtendp->fileline(), enExtendp}; return new AstNot{enExtendp->fileline(), enExtendp};
} else if (AstSel* const selp = VN_CAST(nodep, Sel)) { } else if (AstSel* const selp = VN_CAST(nodep, Sel)) {
AstNodeExpr* const fromp = selp->fromp()->unlinkFrBack(); AstNodeExpr* const fromp = selp->fromp()->unlinkFrBack();
AstSel* const enSelp = selp->cloneTree(false); AstSel* const enSelp = selp->cloneTreePure(false);
selp->fromp(fromp); selp->fromp(fromp);
AstNodeExpr* const enFromp = getEnExprBasedOnOriginalp(fromp); AstNodeExpr* const enFromp = getEnExprBasedOnOriginalp(fromp);
enSelp->fromp(enFromp); enSelp->fromp(enFromp);
@ -572,7 +572,7 @@ class TristateVisitor final : public TristateBaseVisitor {
// Would be nicer if we made this a new AST type // Would be nicer if we made this a new AST type
AstNodeExpr* const newp = new AstShiftL{ AstNodeExpr* const newp = new AstShiftL{
selp->fileline(), new AstExtend{selp->fileline(), enp, selp->fromp()->width()}, selp->fileline(), new AstExtend{selp->fileline(), enp, selp->fromp()->width()},
selp->lsbp()->cloneTree(false), selp->fromp()->width()}; selp->lsbp()->cloneTreePure(false), selp->fromp()->width()};
return newp; return newp;
} }
@ -779,7 +779,7 @@ class TristateVisitor final : public TristateBaseVisitor {
// If weaker driver should be overwritten by a stronger, replace its value with z // If weaker driver should be overwritten by a stronger, replace its value with z
exprCurrentStrengthp exprCurrentStrengthp
= new AstAnd{fl, new AstVarRef{fl, varStrengthp, VAccess::READ}, = new AstAnd{fl, new AstVarRef{fl, varStrengthp, VAccess::READ},
new AstNot{fl, enp->cloneTree(false)}}; new AstNot{fl, enp->cloneTreePure(false)}};
} else { } else {
exprCurrentStrengthp = new AstVarRef{fl, varStrengthp, VAccess::READ}; exprCurrentStrengthp = new AstVarRef{fl, varStrengthp, VAccess::READ};
} }
@ -1086,7 +1086,7 @@ class TristateVisitor final : public TristateBaseVisitor {
if (nodep->fromp()->user1p()) { // SEL(VARREF, lsb) if (nodep->fromp()->user1p()) { // SEL(VARREF, lsb)
AstNodeExpr* const en1p = getEnp(nodep->fromp()); AstNodeExpr* const en1p = getEnp(nodep->fromp());
AstNodeExpr* const enp AstNodeExpr* const enp
= new AstSel{nodep->fileline(), en1p, nodep->lsbp()->cloneTree(true), = new AstSel{nodep->fileline(), en1p, nodep->lsbp()->cloneTreePure(true),
nodep->widthp()->cloneTree(true)}; nodep->widthp()->cloneTree(true)};
UINFO(9, " newsel " << enp << endl); UINFO(9, " newsel " << enp << endl);
nodep->user1p(enp); // propagate up SEL(fromp->enable, value) nodep->user1p(enp); // propagate up SEL(fromp->enable, value)
@ -1113,7 +1113,7 @@ class TristateVisitor final : public TristateBaseVisitor {
// Each half of the concat gets a select of the enable expression // Each half of the concat gets a select of the enable expression
AstNodeExpr* const enp = VN_AS(nodep->user1p(), NodeExpr); AstNodeExpr* const enp = VN_AS(nodep->user1p(), NodeExpr);
nodep->user1p(nullptr); nodep->user1p(nullptr);
nodep->lhsp()->user1p(new AstSel{nodep->fileline(), enp->cloneTree(true), nodep->lhsp()->user1p(new AstSel{nodep->fileline(), enp->cloneTreePure(true),
nodep->rhsp()->width(), nodep->rhsp()->width(),
nodep->lhsp()->width()}); nodep->lhsp()->width()});
nodep->rhsp()->user1p( nodep->rhsp()->user1p(
@ -1208,8 +1208,8 @@ class TristateVisitor final : public TristateBaseVisitor {
m_tgraph.didProcess(nodep); m_tgraph.didProcess(nodep);
AstNodeExpr* const en1p = getEnp(expr1p); AstNodeExpr* const en1p = getEnp(expr1p);
AstNodeExpr* const en2p = getEnp(expr2p); AstNodeExpr* const en2p = getEnp(expr2p);
AstNodeExpr* subexpr1p = expr1p->cloneTree(false); AstNodeExpr* subexpr1p = expr1p->cloneTreePure(false);
AstNodeExpr* subexpr2p = expr2p->cloneTree(false); AstNodeExpr* subexpr2p = expr2p->cloneTreePure(false);
if (isAnd) { if (isAnd) {
subexpr1p = new AstNot{nodep->fileline(), subexpr1p}; subexpr1p = new AstNot{nodep->fileline(), subexpr1p};
subexpr2p = new AstNot{nodep->fileline(), subexpr2p}; subexpr2p = new AstNot{nodep->fileline(), subexpr2p};
@ -1407,15 +1407,15 @@ class TristateVisitor final : public TristateBaseVisitor {
if (nonXp) { // Need to still count '0 or '1 or 'x's if (nonXp) { // Need to still count '0 or '1 or 'x's
if (dropop[0]) { if (dropop[0]) {
nodep->rhsp()->unlinkFrBack()->deleteTree(); nodep->rhsp()->unlinkFrBack()->deleteTree();
nodep->rhsp(nonXp->cloneTree(true)); nodep->rhsp(nonXp->cloneTreePure(true));
} }
if (dropop[1]) { if (dropop[1]) {
nodep->thsp()->unlinkFrBack()->deleteTree(); nodep->thsp()->unlinkFrBack()->deleteTree();
nodep->thsp(nonXp->cloneTree(true)); nodep->thsp(nonXp->cloneTreePure(true));
} }
if (dropop[2]) { if (dropop[2]) {
nodep->fhsp()->unlinkFrBack()->deleteTree(); nodep->fhsp()->unlinkFrBack()->deleteTree();
nodep->fhsp(nonXp->cloneTree(true)); nodep->fhsp(nonXp->cloneTreePure(true));
} }
newp = new AstAdd{nodep->fileline(), nodep, newp}; newp = new AstAdd{nodep->fileline(), nodep, newp};
} }
@ -1582,8 +1582,8 @@ class TristateVisitor final : public TristateBaseVisitor {
<< nodep->prettyNameQ()); << nodep->prettyNameQ());
} }
} else { } else {
AstNodeExpr* const outexprp AstNodeExpr* const outexprp = VN_AS(nodep->exprp(), NodeExpr)
= VN_AS(nodep->exprp(), NodeExpr)->cloneTree(false); // Note has lvalue() set ->cloneTreePure(false); // Note has lvalue() set
outpinp = new AstPin{nodep->fileline(), nodep->pinNum(), outpinp = new AstPin{nodep->fileline(), nodep->pinNum(),
outModVarp->name(), // should be {var}"__out" outModVarp->name(), // should be {var}"__out"
outexprp}; outexprp};

View File

@ -306,15 +306,15 @@ private:
} }
if (dropop[0]) { if (dropop[0]) {
nodep->rhsp()->unlinkFrBack()->deleteTree(); nodep->rhsp()->unlinkFrBack()->deleteTree();
nodep->rhsp(nonXp->cloneTree(true)); nodep->rhsp(nonXp->cloneTreePure(true));
} }
if (dropop[1]) { if (dropop[1]) {
nodep->thsp()->unlinkFrBack()->deleteTree(); nodep->thsp()->unlinkFrBack()->deleteTree();
nodep->thsp(nonXp->cloneTree(true)); nodep->thsp(nonXp->cloneTreePure(true));
} }
if (dropop[2]) { if (dropop[2]) {
nodep->fhsp()->unlinkFrBack()->deleteTree(); nodep->fhsp()->unlinkFrBack()->deleteTree();
nodep->fhsp(nonXp->cloneTree(true)); nodep->fhsp(nonXp->cloneTreePure(true));
} }
iterateChildren(nodep); iterateChildren(nodep);
} }
@ -398,7 +398,7 @@ private:
= new AstGte{nodep->fileline(), = new AstGte{nodep->fileline(),
new AstConst(nodep->fileline(), AstConst::WidthedValue{}, new AstConst(nodep->fileline(), AstConst::WidthedValue{},
nodep->lsbp()->width(), maxmsb), nodep->lsbp()->width(), maxmsb),
nodep->lsbp()->cloneTree(false)}; nodep->lsbp()->cloneTreePure(false)};
// See if the condition is constant true (e.g. always in bound due to constant select) // See if the condition is constant true (e.g. always in bound due to constant select)
// Note below has null backp(); the Edit function knows how to deal with that. // Note below has null backp(); the Edit function knows how to deal with that.
condp = V3Const::constifyEdit(condp); condp = V3Const::constifyEdit(condp);
@ -457,7 +457,7 @@ private:
= new AstGte{nodep->fileline(), = new AstGte{nodep->fileline(),
new AstConst(nodep->fileline(), AstConst::WidthedValue{}, new AstConst(nodep->fileline(), AstConst::WidthedValue{},
nodep->bitp()->width(), declElements - 1), nodep->bitp()->width(), declElements - 1),
nodep->bitp()->cloneTree(false)}; nodep->bitp()->cloneTreePure(false)};
// Note below has null backp(); the Edit function knows how to deal with that. // Note below has null backp(); the Edit function knows how to deal with that.
condp = V3Const::constifyEdit(condp); condp = V3Const::constifyEdit(condp);
if (condp->isOne()) { if (condp->isOne()) {

View File

@ -1858,7 +1858,7 @@ private:
if (assoc) { if (assoc) {
AstVar* const varp = enumVarp(enumDtp, VAttrType::ENUM_VALID, true, 0); AstVar* const varp = enumVarp(enumDtp, VAttrType::ENUM_VALID, true, 0);
testp = new AstAssocSel{fl_novalue, newVarRefDollarUnit(varp), testp = new AstAssocSel{fl_novalue, newVarRefDollarUnit(varp),
nodep->fromp()->cloneTree(false)}; nodep->fromp()->cloneTreePure(false)};
} else { } else {
const int selwidth = V3Number::log2b(maxval) + 1; // Width to address a bit const int selwidth = V3Number::log2b(maxval) + 1; // Width to address a bit
AstVar* const varp AstVar* const varp
@ -1867,12 +1867,12 @@ private:
fl_nowidth->warnOff(V3ErrorCode::WIDTH, true); fl_nowidth->warnOff(V3ErrorCode::WIDTH, true);
testp = new AstCond{ testp = new AstCond{
fl, fl,
new AstGt{fl_nowidth, nodep->fromp()->cloneTree(false), new AstGt{fl_nowidth, nodep->fromp()->cloneTreePure(false),
new AstConst{fl_nowidth, AstConst::Unsized64{}, maxval}}, new AstConst{fl_nowidth, AstConst::Unsized64{}, maxval}},
new AstConst{fl, AstConst::BitFalse{}}, new AstConst{fl, AstConst::BitFalse{}},
new AstArraySel{ new AstArraySel{fl, newVarRefDollarUnit(varp),
fl, newVarRefDollarUnit(varp), new AstSel{fl_novalue, nodep->fromp()->cloneTreePure(false), 0,
new AstSel{fl_novalue, nodep->fromp()->cloneTree(false), 0, selwidth}}}; selwidth}}};
} }
newp = new AstCond{ newp = new AstCond{
fl, testp, fl, testp,
@ -2550,7 +2550,7 @@ private:
"Inside operator not legal on non-unpacked arrays (IEEE 1800-2017 11.4.13)"); "Inside operator not legal on non-unpacked arrays (IEEE 1800-2017 11.4.13)");
continue; continue;
} else { } else {
inewp = AstEqWild::newTyped(itemp->fileline(), nodep->exprp()->cloneTree(true), inewp = AstEqWild::newTyped(itemp->fileline(), nodep->exprp()->cloneTreePure(true),
itemp->unlinkFrBack()); itemp->unlinkFrBack());
} }
if (newp) { if (newp) {
@ -3625,7 +3625,7 @@ private:
FileLine* const fl = nodep->fileline(); FileLine* const fl = nodep->fileline();
AstNodeExpr* newp = nullptr; AstNodeExpr* newp = nullptr;
for (int i = 0; i < adtypep->elementsConst(); ++i) { for (int i = 0; i < adtypep->elementsConst(); ++i) {
AstNodeExpr* const arrayRef = nodep->fromp()->cloneTree(false); AstNodeExpr* const arrayRef = nodep->fromp()->cloneTreePure(false);
AstNodeExpr* const selector = new AstArraySel{fl, arrayRef, i}; AstNodeExpr* const selector = new AstArraySel{fl, arrayRef, i};
if (!newp) { if (!newp) {
newp = selector; newp = selector;
@ -4552,8 +4552,9 @@ private:
if (adtypep->isString()) { if (adtypep->isString()) {
if (varp) { if (varp) {
AstConst* const leftp = new AstConst{fl, AstConst::Signed32{}, 0}; AstConst* const leftp = new AstConst{fl, AstConst::Signed32{}, 0};
AstLt* const condp = new AstLt{fl, new AstVarRef{fl, varp, VAccess::READ}, AstLt* const condp
new AstLenN{fl, fromp->cloneTree(false)}}; = new AstLt{fl, new AstVarRef{fl, varp, VAccess::READ},
new AstLenN{fl, fromp->cloneTreePure(false)}};
AstAdd* const incp AstAdd* const incp
= new AstAdd{fl, new AstConst{fl, AstConst::Signed32{}, 1}, = new AstAdd{fl, new AstConst{fl, AstConst::Signed32{}, 1},
new AstVarRef{fl, varp, VAccess::READ}}; new AstVarRef{fl, varp, VAccess::READ}};
@ -4576,7 +4577,8 @@ private:
} else if (VN_IS(fromDtp, DynArrayDType) || VN_IS(fromDtp, QueueDType)) { } else if (VN_IS(fromDtp, DynArrayDType) || VN_IS(fromDtp, QueueDType)) {
if (varp) { if (varp) {
auto* const leftp = new AstConst{fl, AstConst::Signed32{}, 0}; auto* const leftp = new AstConst{fl, AstConst::Signed32{}, 0};
auto* const sizep = new AstCMethodHard{fl, fromp->cloneTree(false), "size"}; auto* const sizep
= new AstCMethodHard{fl, fromp->cloneTreePure(false), "size"};
sizep->dtypeSetSigned32(); sizep->dtypeSetSigned32();
sizep->didWidth(true); sizep->didWidth(true);
sizep->protect(false); sizep->protect(false);
@ -4601,10 +4603,10 @@ private:
fl, VVarType::BLOCKTEMP, varp->name() + "__Vfirst", VFlagBitPacked{}, 1}; fl, VVarType::BLOCKTEMP, varp->name() + "__Vfirst", VFlagBitPacked{}, 1};
first_varp->usedLoopIdx(true); first_varp->usedLoopIdx(true);
AstNodeExpr* const firstp = new AstMethodCall{ AstNodeExpr* const firstp = new AstMethodCall{
fl, fromp->cloneTree(false), "first", fl, fromp->cloneTreePure(false), "first",
new AstArg{fl, "", new AstVarRef{fl, varp, VAccess::READWRITE}}}; new AstArg{fl, "", new AstVarRef{fl, varp, VAccess::READWRITE}}};
AstNodeExpr* const nextp = new AstMethodCall{ AstNodeExpr* const nextp = new AstMethodCall{
fl, fromp->cloneTree(false), "next", fl, fromp->cloneTreePure(false), "next",
new AstArg{fl, "", new AstVarRef{fl, varp, VAccess::READWRITE}}}; new AstArg{fl, "", new AstVarRef{fl, varp, VAccess::READWRITE}}};
AstNode* const first_clearp AstNode* const first_clearp
= new AstAssign{fl, new AstVarRef{fl, first_varp, VAccess::WRITE}, = new AstAssign{fl, new AstVarRef{fl, first_varp, VAccess::WRITE},

View File

@ -961,6 +961,9 @@ def write_ast_macros(filename):
Ast{t}* cloneTree(bool cloneNext) {{ Ast{t}* cloneTree(bool cloneNext) {{
return static_cast<Ast{t}*>(AstNode::cloneTree(cloneNext)); return static_cast<Ast{t}*>(AstNode::cloneTree(cloneNext));
}} }}
Ast{t}* cloneTreePure(bool cloneNext) {{
return static_cast<Ast{t}*>(AstNode::cloneTreePure(cloneNext));
}}
Ast{t}* clonep() const {{ return static_cast<Ast{t}*>(AstNode::clonep()); }} Ast{t}* clonep() const {{ return static_cast<Ast{t}*>(AstNode::clonep()); }}
Ast{t}* addNext(Ast{t}* nodep) {{ return static_cast<Ast{t}*>(AstNode::addNext(this, nodep)); }} Ast{t}* addNext(Ast{t}* nodep) {{ return static_cast<Ast{t}*>(AstNode::addNext(this, nodep)); }}
''', ''',

View File

@ -2885,40 +2885,40 @@ genvar_iteration<nodep>: // ==IEEE: genvar_iteration
varRefBase '=' expr varRefBase '=' expr
{ $$ = new AstAssign{$2, $1, $3}; } { $$ = new AstAssign{$2, $1, $3}; }
| varRefBase yP_PLUSEQ expr | varRefBase yP_PLUSEQ expr
{ $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTreePure(true), $3}}; }
| varRefBase yP_MINUSEQ expr | varRefBase yP_MINUSEQ expr
{ $$ = new AstAssign{$2, $1, new AstSub{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstSub{$2, $1->cloneTreePure(true), $3}}; }
| varRefBase yP_TIMESEQ expr | varRefBase yP_TIMESEQ expr
{ $$ = new AstAssign{$2, $1, new AstMul{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstMul{$2, $1->cloneTreePure(true), $3}}; }
| varRefBase yP_DIVEQ expr | varRefBase yP_DIVEQ expr
{ $$ = new AstAssign{$2, $1, new AstDiv{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstDiv{$2, $1->cloneTreePure(true), $3}}; }
| varRefBase yP_MODEQ expr | varRefBase yP_MODEQ expr
{ $$ = new AstAssign{$2, $1, new AstModDiv{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstModDiv{$2, $1->cloneTreePure(true), $3}}; }
| varRefBase yP_ANDEQ expr | varRefBase yP_ANDEQ expr
{ $$ = new AstAssign{$2, $1, new AstAnd{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstAnd{$2, $1->cloneTreePure(true), $3}}; }
| varRefBase yP_OREQ expr | varRefBase yP_OREQ expr
{ $$ = new AstAssign{$2, $1, new AstOr{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstOr{$2, $1->cloneTreePure(true), $3}}; }
| varRefBase yP_XOREQ expr | varRefBase yP_XOREQ expr
{ $$ = new AstAssign{$2, $1, new AstXor{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstXor{$2, $1->cloneTreePure(true), $3}}; }
| varRefBase yP_SLEFTEQ expr | varRefBase yP_SLEFTEQ expr
{ $$ = new AstAssign{$2, $1, new AstShiftL{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstShiftL{$2, $1->cloneTreePure(true), $3}}; }
| varRefBase yP_SRIGHTEQ expr | varRefBase yP_SRIGHTEQ expr
{ $$ = new AstAssign{$2, $1, new AstShiftR{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstShiftR{$2, $1->cloneTreePure(true), $3}}; }
| varRefBase yP_SSRIGHTEQ expr | varRefBase yP_SSRIGHTEQ expr
{ $$ = new AstAssign{$2, $1, new AstShiftRS{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstShiftRS{$2, $1->cloneTreePure(true), $3}}; }
// // inc_or_dec_operator // // inc_or_dec_operator
// When support ++ as a real AST type, maybe AstWhile::precondsp() becomes generic AstNodeExprStmt? // When support ++ as a real AST type, maybe AstWhile::precondsp() becomes generic AstNodeExprStmt?
| yP_PLUSPLUS varRefBase | yP_PLUSPLUS varRefBase
{ $$ = new AstAssign{$1, $2, new AstAdd{$1, $2->cloneTree(true), { $$ = new AstAssign{$1, $2, new AstAdd{$1, $2->cloneTreePure(true),
new AstConst{$1, AstConst::StringToParse{}, "'b1"}}}; } new AstConst{$1, AstConst::StringToParse{}, "'b1"}}}; }
| yP_MINUSMINUS varRefBase | yP_MINUSMINUS varRefBase
{ $$ = new AstAssign{$1, $2, new AstSub{$1, $2->cloneTree(true), { $$ = new AstAssign{$1, $2, new AstSub{$1, $2->cloneTreePure(true),
new AstConst{$1, AstConst::StringToParse{}, "'b1"}}}; } new AstConst{$1, AstConst::StringToParse{}, "'b1"}}}; }
| varRefBase yP_PLUSPLUS | varRefBase yP_PLUSPLUS
{ $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTree(true), { $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTreePure(true),
new AstConst{$2, AstConst::StringToParse{}, "'b1"}}}; } new AstConst{$2, AstConst::StringToParse{}, "'b1"}}}; }
| varRefBase yP_MINUSMINUS | varRefBase yP_MINUSMINUS
{ $$ = new AstAssign{$2, $1, new AstSub{$2, $1->cloneTree(true), { $$ = new AstAssign{$2, $1, new AstSub{$2, $1->cloneTreePure(true),
new AstConst{$2, AstConst::StringToParse{}, "'b1"}}}; } new AstConst{$2, AstConst::StringToParse{}, "'b1"}}}; }
; ;
@ -3681,44 +3681,44 @@ foperator_assignment<nodep>: // IEEE: operator_assignment (for first part of
fexprLvalue '=' delay_or_event_controlE expr { $$ = new AstAssign{$2, $1, $4, $3}; } fexprLvalue '=' delay_or_event_controlE expr { $$ = new AstAssign{$2, $1, $4, $3}; }
// //
| fexprLvalue yP_PLUSEQ expr | fexprLvalue yP_PLUSEQ expr
{ $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTreePure(true), $3}}; }
| fexprLvalue yP_MINUSEQ expr | fexprLvalue yP_MINUSEQ expr
{ $$ = new AstAssign{$2, $1, new AstSub{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstSub{$2, $1->cloneTreePure(true), $3}}; }
| fexprLvalue yP_TIMESEQ expr | fexprLvalue yP_TIMESEQ expr
{ $$ = new AstAssign{$2, $1, new AstMul{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstMul{$2, $1->cloneTreePure(true), $3}}; }
| fexprLvalue yP_DIVEQ expr | fexprLvalue yP_DIVEQ expr
{ $$ = new AstAssign{$2, $1, new AstDiv{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstDiv{$2, $1->cloneTreePure(true), $3}}; }
| fexprLvalue yP_MODEQ expr | fexprLvalue yP_MODEQ expr
{ $$ = new AstAssign{$2, $1, new AstModDiv{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstModDiv{$2, $1->cloneTreePure(true), $3}}; }
| fexprLvalue yP_ANDEQ expr | fexprLvalue yP_ANDEQ expr
{ $$ = new AstAssign{$2, $1, new AstAnd{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstAnd{$2, $1->cloneTreePure(true), $3}}; }
| fexprLvalue yP_OREQ expr | fexprLvalue yP_OREQ expr
{ $$ = new AstAssign{$2, $1, new AstOr{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstOr{$2, $1->cloneTreePure(true), $3}}; }
| fexprLvalue yP_XOREQ expr | fexprLvalue yP_XOREQ expr
{ $$ = new AstAssign{$2, $1, new AstXor{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstXor{$2, $1->cloneTreePure(true), $3}}; }
| fexprLvalue yP_SLEFTEQ expr | fexprLvalue yP_SLEFTEQ expr
{ $$ = new AstAssign{$2, $1, new AstShiftL{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstShiftL{$2, $1->cloneTreePure(true), $3}}; }
| fexprLvalue yP_SRIGHTEQ expr | fexprLvalue yP_SRIGHTEQ expr
{ $$ = new AstAssign{$2, $1, new AstShiftR{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstShiftR{$2, $1->cloneTreePure(true), $3}}; }
| fexprLvalue yP_SSRIGHTEQ expr | fexprLvalue yP_SSRIGHTEQ expr
{ $$ = new AstAssign{$2, $1, new AstShiftRS{$2, $1->cloneTree(true), $3}}; } { $$ = new AstAssign{$2, $1, new AstShiftRS{$2, $1->cloneTreePure(true), $3}}; }
; ;
inc_or_dec_expression<nodeExprp>: // ==IEEE: inc_or_dec_expression inc_or_dec_expression<nodeExprp>: // ==IEEE: inc_or_dec_expression
// // Need fexprScope instead of variable_lvalue to prevent conflict // // Need fexprScope instead of variable_lvalue to prevent conflict
~l~exprScope yP_PLUSPLUS ~l~exprScope yP_PLUSPLUS
{ $<fl>$ = $<fl>1; $$ = new AstPostAdd{$2, new AstConst{$2, AstConst::StringToParse{}, "'b1"}, { $<fl>$ = $<fl>1; $$ = new AstPostAdd{$2, new AstConst{$2, AstConst::StringToParse{}, "'b1"},
$1, $1->cloneTree(true)}; } $1, $1->cloneTreePure(true)}; }
| ~l~exprScope yP_MINUSMINUS | ~l~exprScope yP_MINUSMINUS
{ $<fl>$ = $<fl>1; $$ = new AstPostSub{$2, new AstConst{$2, AstConst::StringToParse{}, "'b1"}, { $<fl>$ = $<fl>1; $$ = new AstPostSub{$2, new AstConst{$2, AstConst::StringToParse{}, "'b1"},
$1, $1->cloneTree(true)}; } $1, $1->cloneTreePure(true)}; }
// // Need expr instead of variable_lvalue to prevent conflict // // Need expr instead of variable_lvalue to prevent conflict
| yP_PLUSPLUS expr | yP_PLUSPLUS expr
{ $<fl>$ = $<fl>1; $$ = new AstPreAdd{$1, new AstConst{$1, AstConst::StringToParse{}, "'b1"}, { $<fl>$ = $<fl>1; $$ = new AstPreAdd{$1, new AstConst{$1, AstConst::StringToParse{}, "'b1"},
$2, $2->cloneTree(true)}; } $2, $2->cloneTreePure(true)}; }
| yP_MINUSMINUS expr | yP_MINUSMINUS expr
{ $<fl>$ = $<fl>1; $$ = new AstPreSub{$1, new AstConst{$1, AstConst::StringToParse{}, "'b1"}, { $<fl>$ = $<fl>1; $$ = new AstPreSub{$1, new AstConst{$1, AstConst::StringToParse{}, "'b1"},
$2, $2->cloneTree(true)}; } $2, $2->cloneTreePure(true)}; }
; ;
finc_or_dec_expression<nodeExprp>: // ==IEEE: inc_or_dec_expression finc_or_dec_expression<nodeExprp>: // ==IEEE: inc_or_dec_expression
@ -4734,40 +4734,40 @@ expr<nodeExprp>: // IEEE: part of expression/constant_expression/
// // Need exprScope of variable_lvalue to prevent conflict // // Need exprScope of variable_lvalue to prevent conflict
| '(' ~p~exprScope '=' expr ')' | '(' ~p~exprScope '=' expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, $4}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, $4},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_PLUSEQ expr ')' | '(' ~p~exprScope yP_PLUSEQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstAdd{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstAdd{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_MINUSEQ expr ')' | '(' ~p~exprScope yP_MINUSEQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstSub{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstSub{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_TIMESEQ expr ')' | '(' ~p~exprScope yP_TIMESEQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstMul{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstMul{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_DIVEQ expr ')' | '(' ~p~exprScope yP_DIVEQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstDiv{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstDiv{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_MODEQ expr ')' | '(' ~p~exprScope yP_MODEQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstModDiv{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstModDiv{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_ANDEQ expr ')' | '(' ~p~exprScope yP_ANDEQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstAnd{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstAnd{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_OREQ expr ')' | '(' ~p~exprScope yP_OREQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstOr{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstOr{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_XOREQ expr ')' | '(' ~p~exprScope yP_XOREQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstXor{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstXor{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_SLEFTEQ expr ')' | '(' ~p~exprScope yP_SLEFTEQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstShiftL{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstShiftL{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_SRIGHTEQ expr ')' | '(' ~p~exprScope yP_SRIGHTEQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstShiftR{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstShiftR{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
| '(' ~p~exprScope yP_SSRIGHTEQ expr ')' | '(' ~p~exprScope yP_SSRIGHTEQ expr ')'
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstShiftRS{$3, $2->cloneTree(true), $4}}, { $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstShiftRS{$3, $2->cloneTreePure(true), $4}},
$2->cloneTree(true)}; } $2->cloneTreePure(true)}; }
// //
// // IEEE: expression binary_operator expression // // IEEE: expression binary_operator expression
| ~l~expr '+' ~r~expr { $$ = new AstAdd{$2, $1, $3}; } | ~l~expr '+' ~r~expr { $$ = new AstAdd{$2, $1, $3}; }