astgen: Enforce the use of aliased operand accessors (#4688)

This patch enforces the use of the most specific accessors for operands
which have an '@astgen alias' declaration, by making the superclass
accessors of the same operands private. This ensures client code is
cleaner as you can't use multiple different methods to reference the
same operands (which we used to in some places). Also prep for some
refactoring.
This commit is contained in:
Geza Lore 2023-11-12 18:30:48 +00:00 committed by GitHub
parent 1c0af6c7bc
commit 47588f343b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 106 additions and 86 deletions

View File

@ -4311,7 +4311,7 @@ class AstSelMinus final : public AstNodePreSel {
// -: range extraction, perhaps with non-constant selection // -: range extraction, perhaps with non-constant selection
// Gets replaced during link with AstSel // Gets replaced during link with AstSel
// @astgen alias op2 := bitp // @astgen alias op2 := bitp
// @astgen alias op3 := widtph // @astgen alias op3 := widthp
public: public:
AstSelMinus(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp, AstNodeExpr* widthp) AstSelMinus(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp, AstNodeExpr* widthp)
: ASTGEN_SUPER_SelMinus(fl, fromp, bitp, widthp) {} : ASTGEN_SUPER_SelMinus(fl, fromp, bitp, widthp) {}
@ -4321,7 +4321,7 @@ class AstSelPlus final : public AstNodePreSel {
// +: range extraction, perhaps with non-constant selection // +: range extraction, perhaps with non-constant selection
// Gets replaced during link with AstSel // Gets replaced during link with AstSel
// @astgen alias op2 := bitp // @astgen alias op2 := bitp
// @astgen alias op3 := widtph // @astgen alias op3 := widthp
public: public:
AstSelPlus(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp, AstNodeExpr* widthp) AstSelPlus(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp, AstNodeExpr* widthp)
: ASTGEN_SUPER_SelPlus(fl, fromp, bitp, widthp) {} : ASTGEN_SUPER_SelPlus(fl, fromp, bitp, widthp) {}

View File

@ -462,7 +462,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
void visit(AstWordSel* nodep) override { void visit(AstWordSel* nodep) override {
CONST_BITOP_RETURN_IF(!m_leafp, nodep); CONST_BITOP_RETURN_IF(!m_leafp, nodep);
AstConst* const constp = VN_CAST(nodep->bitp(), Const); AstConst* const constp = VN_CAST(nodep->bitp(), Const);
CONST_BITOP_RETURN_IF(!constp, nodep->rhsp()); CONST_BITOP_RETURN_IF(!constp, nodep->bitp());
UASSERT_OBJ(m_leafp->wordIdx() == -1, nodep, "Unexpected nested WordSel"); UASSERT_OBJ(m_leafp->wordIdx() == -1, nodep, "Unexpected nested WordSel");
m_leafp->wordIdx(constp->toSInt()); m_leafp->wordIdx(constp->toSInt());
iterateConst(nodep->fromp()); iterateConst(nodep->fromp());
@ -1269,9 +1269,9 @@ private:
// V3Expand may make a arraysel that exceeds the bounds of the array // V3Expand may make a arraysel that exceeds the bounds of the array
// It was an expression, then got constified. In reality, the WordSel // It was an expression, then got constified. In reality, the WordSel
// must be wrapped in a Cond, that will be false. // must be wrapped in a Cond, that will be false.
return (VN_IS(nodep->rhsp(), Const) && VN_IS(nodep->fromp(), NodeVarRef) return (VN_IS(nodep->bitp(), Const) && VN_IS(nodep->fromp(), NodeVarRef)
&& VN_AS(nodep->fromp(), NodeVarRef)->access().isReadOnly() && VN_AS(nodep->fromp(), NodeVarRef)->access().isReadOnly()
&& (static_cast<int>(VN_AS(nodep->rhsp(), Const)->toUInt()) && (static_cast<int>(VN_AS(nodep->bitp(), Const)->toUInt())
>= VN_AS(nodep->fromp(), NodeVarRef)->varp()->widthWords())); >= VN_AS(nodep->fromp(), NodeVarRef)->varp()->widthWords()));
} }
bool operandSelFull(const AstSel* nodep) { bool operandSelFull(const AstSel* nodep) {
@ -2539,7 +2539,7 @@ private:
// SEL(REPLICATE(from,rep),lsb,width) => SEL(from,0,width) as long // SEL(REPLICATE(from,rep),lsb,width) => SEL(from,0,width) as long
// as SEL's width <= b's width // as SEL's width <= b's width
AstReplicate* const repp = VN_AS(nodep->fromp(), Replicate); AstReplicate* const repp = VN_AS(nodep->fromp(), Replicate);
AstNodeExpr* const fromp = repp->lhsp(); AstNodeExpr* const fromp = repp->srcp();
AstConst* const lsbp = VN_CAST(nodep->lsbp(), Const); AstConst* const lsbp = VN_CAST(nodep->lsbp(), Const);
if (!lsbp) return false; if (!lsbp) return false;
AstNodeExpr* const widthp = nodep->widthp(); AstNodeExpr* const widthp = nodep->widthp();
@ -2562,11 +2562,11 @@ private:
} }
bool operandRepRep(AstReplicate* nodep) { bool operandRepRep(AstReplicate* nodep) {
// REPLICATE(REPLICATE2(from2,cnt2),cnt1) => REPLICATE(from2,(cnt1+cnt2)) // REPLICATE(REPLICATE2(from2,cnt2),cnt1) => REPLICATE(from2,(cnt1+cnt2))
AstReplicate* const rep2p = VN_AS(nodep->lhsp(), Replicate); AstReplicate* const rep2p = VN_AS(nodep->srcp(), Replicate);
AstNodeExpr* const from2p = rep2p->lhsp(); AstNodeExpr* const from2p = rep2p->srcp();
AstConst* const cnt1p = VN_CAST(nodep->rhsp(), Const); AstConst* const cnt1p = VN_CAST(nodep->countp(), Const);
if (!cnt1p) return false; if (!cnt1p) return false;
AstConst* const cnt2p = VN_CAST(rep2p->rhsp(), Const); AstConst* const cnt2p = VN_CAST(rep2p->countp(), Const);
if (!cnt2p) return false; if (!cnt2p) return false;
// //
from2p->unlinkFrBack(); from2p->unlinkFrBack();
@ -2589,15 +2589,15 @@ private:
AstNodeExpr* from2p = nodep->rhsp(); AstNodeExpr* from2p = nodep->rhsp();
uint32_t cnt2 = 1; uint32_t cnt2 = 1;
if (VN_IS(from1p, Replicate)) { if (VN_IS(from1p, Replicate)) {
AstConst* const cnt1p = VN_CAST(VN_CAST(from1p, Replicate)->rhsp(), Const); AstConst* const cnt1p = VN_CAST(VN_CAST(from1p, Replicate)->countp(), Const);
if (!cnt1p) return false; if (!cnt1p) return false;
from1p = VN_AS(from1p, Replicate)->lhsp(); from1p = VN_AS(from1p, Replicate)->srcp();
cnt1 = cnt1p->toUInt(); cnt1 = cnt1p->toUInt();
} }
if (VN_IS(from2p, Replicate)) { if (VN_IS(from2p, Replicate)) {
AstConst* const cnt2p = VN_CAST(VN_CAST(from2p, Replicate)->rhsp(), Const); AstConst* const cnt2p = VN_CAST(VN_CAST(from2p, Replicate)->countp(), Const);
if (!cnt2p) return false; if (!cnt2p) return false;
from2p = VN_AS(from2p, Replicate)->lhsp(); from2p = VN_AS(from2p, Replicate)->srcp();
cnt2 = cnt2p->toUInt(); cnt2 = cnt2p->toUInt();
} }
if (!operandsSame(from1p, from2p)) return false; if (!operandsSame(from1p, from2p)) return false;
@ -3488,8 +3488,8 @@ private:
TREEOPA("AstNodeCond{$condp.isNeqZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$thenp)"); TREEOPA("AstNodeCond{$condp.isNeqZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$thenp)");
TREEOP ("AstNodeCond{$condp, operandsSame($thenp,,$elsep)}","replaceWChild(nodep,$thenp)"); TREEOP ("AstNodeCond{$condp, operandsSame($thenp,,$elsep)}","replaceWChild(nodep,$thenp)");
// This visit function here must allow for short-circuiting. // This visit function here must allow for short-circuiting.
TREEOPS("AstCond {$lhsp.isZero}", "replaceWIteratedThs(nodep)"); TREEOPS("AstCond {$condp.isZero}", "replaceWIteratedThs(nodep)");
TREEOPS("AstCond {$lhsp.isNeqZero}", "replaceWIteratedRhs(nodep)"); TREEOPS("AstCond {$condp.isNeqZero}", "replaceWIteratedRhs(nodep)");
TREEOP ("AstCond{$condp.castNot, $thenp, $elsep}", "AstCond{$condp->castNot()->lhsp(), $elsep, $thenp}"); TREEOP ("AstCond{$condp.castNot, $thenp, $elsep}", "AstCond{$condp->castNot()->lhsp(), $elsep, $thenp}");
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp.isAllOnes, $elsep}", "AstLogOr {$condp, $elsep}"); // a?1:b == a||b TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp.isAllOnes, $elsep}", "AstLogOr {$condp, $elsep}"); // a?1:b == a||b
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp, $elsep.isZero, !$elsep.isClassHandleValue}", "AstLogAnd{$condp, $thenp}"); // a?b:0 == a&&b TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp, $elsep.isZero, !$elsep.isClassHandleValue}", "AstLogAnd{$condp, $thenp}"); // a?b:0 == a&&b
@ -3670,9 +3670,9 @@ private:
// bits end up in the wrong places // bits end up in the wrong places
TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, VN_AS(nodep->lhsp(), Extend)->lhsp())"); TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, VN_AS(nodep->lhsp(), Extend)->lhsp())");
TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, VN_AS(nodep->lhsp(), ExtendS)->lhsp())"); TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, VN_AS(nodep->lhsp(), ExtendS)->lhsp())");
TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs TREEOPV("AstReplicate{$srcp, $countp.isOne, $srcp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
TREEOPV("AstReplicateN{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs TREEOPV("AstReplicateN{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
TREEOPV("AstReplicate{$lhsp.castReplicate, operandRepRep(nodep)}", "DONE"); // {2{3{lhs}}}->{6{lhs}} TREEOPV("AstReplicate{$srcp.castReplicate, operandRepRep(nodep)}", "DONE"); // {2{3{lhs}}}->{6{lhs}}
TREEOPV("AstConcat{operandConcatSame(nodep)}", "DONE"); // {a,a}->{2{a}}, {a,2{a}}->{3{a}, etc TREEOPV("AstConcat{operandConcatSame(nodep)}", "DONE"); // {a,a}->{2{a}}, {a,2{a}}->{3{a}, etc
// Next rule because AUTOINST puts the width of bits in // Next rule because AUTOINST puts the width of bits in
// to pins, even when the widths are exactly the same across the hierarchy. // to pins, even when the widths are exactly the same across the hierarchy.
@ -3694,9 +3694,9 @@ private:
// win if bit select is a constant (otherwise we may need to compute bit index several times) // win if bit select is a constant (otherwise we may need to compute bit index several times)
TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)"); TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)");
TREEOPV("AstSel{$fromp.castNot}", "replaceSelIntoUniop(nodep)"); TREEOPV("AstSel{$fromp.castNot}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castAnd,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); TREEOPV("AstSel{$fromp.castAnd,$fromp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castOr,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); TREEOPV("AstSel{$fromp.castOr,$fromp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castXor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); TREEOPV("AstSel{$fromp.castXor,$fromp.castConst}", "replaceSelIntoUniop(nodep)");
// This visit function here must allow for short-circuiting. // This visit function here must allow for short-circuiting.
TREEOPS("AstLogIf{$lhsp.isZero}", "replaceNum(nodep, 1)"); TREEOPS("AstLogIf{$lhsp.isZero}", "replaceNum(nodep, 1)");
TREEOPV("AstLogIf{$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}"); TREEOPV("AstLogIf{$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");

View File

@ -1184,25 +1184,25 @@ public:
} }
void visit(AstSel* nodep) override { void visit(AstSel* nodep) override {
// Note ASSIGN checks for this on a LHS // Note ASSIGN checks for this on a LHS
emitOpName(nodep, nodep->emitC(), nodep->fromp(), nodep->lsbp(), nodep->thsp()); emitOpName(nodep, nodep->emitC(), nodep->fromp(), nodep->lsbp(), nodep->widthp());
} }
void visit(AstReplicate* nodep) override { void visit(AstReplicate* nodep) override {
if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) { if (nodep->srcp()->widthMin() == 1 && !nodep->isWide()) {
UASSERT_OBJ((static_cast<int>(VN_AS(nodep->rhsp(), Const)->toUInt()) UASSERT_OBJ((static_cast<int>(VN_AS(nodep->countp(), Const)->toUInt())
* nodep->lhsp()->widthMin()) * nodep->srcp()->widthMin())
== nodep->widthMin(), == nodep->widthMin(),
nodep, "Replicate non-constant or width miscomputed"); nodep, "Replicate non-constant or width miscomputed");
puts("VL_REPLICATE_"); puts("VL_REPLICATE_");
emitIQW(nodep); emitIQW(nodep);
puts("OI("); puts("OI(");
if (nodep->lhsp()) puts(cvtToStr(nodep->lhsp()->widthMin())); if (nodep->srcp()) puts(cvtToStr(nodep->srcp()->widthMin()));
puts(","); puts(",");
iterateAndNextConstNull(nodep->lhsp()); iterateAndNextConstNull(nodep->srcp());
puts(", "); puts(", ");
iterateAndNextConstNull(nodep->rhsp()); iterateAndNextConstNull(nodep->countp());
puts(")"); puts(")");
} else { } else {
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr); emitOpName(nodep, nodep->emitC(), nodep->srcp(), nodep->countp(), nullptr);
} }
} }
void visit(AstStreamL* nodep) override { void visit(AstStreamL* nodep) override {
@ -1229,9 +1229,9 @@ public:
} }
void visit(AstCastDynamic* nodep) override { void visit(AstCastDynamic* nodep) override {
putbs("VL_CAST_DYNAMIC("); putbs("VL_CAST_DYNAMIC(");
iterateAndNextConstNull(nodep->lhsp()); iterateAndNextConstNull(nodep->fromp());
puts(", "); puts(", ");
iterateAndNextConstNull(nodep->rhsp()); iterateAndNextConstNull(nodep->top());
puts(")"); puts(")");
} }
void visit(AstCountBits* nodep) override { void visit(AstCountBits* nodep) override {

View File

@ -731,7 +731,7 @@ private:
} else { } else {
if (isImpure(nodep)) return; if (isImpure(nodep)) return;
FileLine* const fl = nodep->fileline(); FileLine* const fl = nodep->fileline();
AstNodeExpr* lhsp = nodep->lhsp()->unlinkFrBack(); AstNodeExpr* lhsp = nodep->srcp()->unlinkFrBack();
AstNodeExpr* newp; AstNodeExpr* newp;
const int lhswidth = lhsp->widthMin(); const int lhswidth = lhsp->widthMin();
if (lhswidth == 1) { if (lhswidth == 1) {
@ -739,7 +739,7 @@ private:
newp = new AstNegate{fl, lhsp}; newp = new AstNegate{fl, lhsp};
} else { } else {
UINFO(8, " REPLICATE " << nodep << endl); UINFO(8, " REPLICATE " << nodep << endl);
const AstConst* const constp = VN_AS(nodep->rhsp(), Const); const AstConst* const constp = VN_AS(nodep->countp(), Const);
UASSERT_OBJ(constp, nodep, UASSERT_OBJ(constp, nodep,
"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();
@ -765,9 +765,9 @@ private:
UINFO(8, " Wordize ASSIGN(REPLICATE) " << nodep << endl); UINFO(8, " Wordize ASSIGN(REPLICATE) " << nodep << endl);
if (!doExpandWide(rhsp)) return false; if (!doExpandWide(rhsp)) return false;
FileLine* const fl = nodep->fileline(); FileLine* const fl = nodep->fileline();
AstNodeExpr* const lhsp = rhsp->lhsp(); AstNodeExpr* const lhsp = rhsp->srcp();
const int lhswidth = lhsp->widthMin(); const int lhswidth = lhsp->widthMin();
const AstConst* const constp = VN_AS(rhsp->rhsp(), Const); const AstConst* const constp = VN_AS(rhsp->countp(), Const);
UASSERT_OBJ(constp, rhsp, "Replication value isn't a constant. Checked earlier!"); UASSERT_OBJ(constp, rhsp, "Replication value isn't a constant. Checked earlier!");
const uint32_t times = constp->toUInt(); const uint32_t times = constp->toUInt();
for (int w = 0; w < rhsp->widthWords(); ++w) { for (int w = 0; w < rhsp->widthWords(); ++w) {

View File

@ -362,11 +362,11 @@ private:
} // end expanding ranged cell } // end expanding ranged cell
else if (AstArraySel* const arrselp = VN_CAST(nodep->exprp(), ArraySel)) { else if (AstArraySel* const arrselp = VN_CAST(nodep->exprp(), ArraySel)) {
if (const AstUnpackArrayDType* const arrp if (const AstUnpackArrayDType* const arrp
= VN_CAST(arrselp->lhsp()->dtypep(), UnpackArrayDType)) { = VN_CAST(arrselp->fromp()->dtypep(), UnpackArrayDType)) {
if (!VN_IS(arrp->subDTypep(), IfaceRefDType)) return; if (!VN_IS(arrp->subDTypep(), IfaceRefDType)) return;
// Interface pin attaches to one element of arrayed interface // Interface pin attaches to one element of arrayed interface
V3Const::constifyParamsEdit(arrselp->rhsp()); V3Const::constifyParamsEdit(arrselp->bitp());
const AstConst* const constp = VN_CAST(arrselp->rhsp(), Const); const AstConst* const constp = VN_CAST(arrselp->bitp(), Const);
if (!constp) { if (!constp) {
nodep->v3warn( nodep->v3warn(
E_UNSUPPORTED, E_UNSUPPORTED,
@ -374,9 +374,9 @@ private:
return; return;
} }
const string index = AstNode::encodeNumber(constp->toSInt()); const string index = AstNode::encodeNumber(constp->toSInt());
if (VN_IS(arrselp->lhsp(), SliceSel)) if (VN_IS(arrselp->fromp(), SliceSel))
arrselp->lhsp()->v3error("Unsupported: interface slices"); arrselp->fromp()->v3error("Unsupported: interface slices");
const AstVarRef* const varrefp = VN_CAST(arrselp->lhsp(), VarRef); const AstVarRef* const varrefp = VN_CAST(arrselp->fromp(), VarRef);
UASSERT_OBJ(varrefp, arrselp, "No interface varref under array"); UASSERT_OBJ(varrefp, arrselp, "No interface varref under array");
AstVarXRef* const newp = new AstVarXRef{ AstVarXRef* const newp = new AstVarXRef{
nodep->fileline(), varrefp->name() + "__BRA__" + index + "__KET__", "", nodep->fileline(), varrefp->name() + "__BRA__" + index + "__KET__", "",

View File

@ -238,19 +238,19 @@ private:
void visit(AstSel* nodep) override { void visit(AstSel* nodep) override {
VL_RESTORER(m_setRefLvalue); VL_RESTORER(m_setRefLvalue);
{ {
iterateAndNextNull(nodep->lhsp()); iterateAndNextNull(nodep->fromp());
// Only set lvalues on the from // Only set lvalues on the from
m_setRefLvalue = VAccess::NOCHANGE; m_setRefLvalue = VAccess::NOCHANGE;
iterateAndNextNull(nodep->rhsp()); iterateAndNextNull(nodep->lsbp());
iterateAndNextNull(nodep->thsp()); iterateAndNextNull(nodep->widthp());
} }
} }
void visit(AstNodeSel* nodep) override { void visit(AstNodeSel* nodep) override {
VL_RESTORER(m_setRefLvalue); VL_RESTORER(m_setRefLvalue);
{ // Only set lvalues on the from { // Only set lvalues on the from
iterateAndNextNull(nodep->lhsp()); iterateAndNextNull(nodep->fromp());
m_setRefLvalue = VAccess::NOCHANGE; m_setRefLvalue = VAccess::NOCHANGE;
iterateAndNextNull(nodep->rhsp()); iterateAndNextNull(nodep->bitp());
} }
} }
void visit(AstCellArrayRef* nodep) override { void visit(AstCellArrayRef* nodep) override {

View File

@ -561,7 +561,7 @@ private:
// Convert to AstSelLoopVars so V3LinkDot knows what's being defined // Convert to AstSelLoopVars so V3LinkDot knows what's being defined
AstNode* const newp AstNode* const newp
= new AstSelLoopVars{selp->fileline(), selp->fromp()->unlinkFrBack(), = new AstSelLoopVars{selp->fileline(), selp->fromp()->unlinkFrBack(),
selp->rhsp()->unlinkFrBackWithNext()}; selp->bitp()->unlinkFrBackWithNext()};
selp->replaceWith(newp); selp->replaceWith(newp);
VL_DO_DANGLING(selp->deleteTree(), selp); VL_DO_DANGLING(selp->deleteTree(), selp);
} else if (VN_IS(bracketp, SelLoopVars)) { } else if (VN_IS(bracketp, SelLoopVars)) {

View File

@ -768,7 +768,7 @@ private:
outVarrefpRef = varrefp; outVarrefpRef = varrefp;
lsbRef = fetchConst(selp->lsbp())->num(); lsbRef = fetchConst(selp->lsbp())->num();
return; // And presumably still optimizable() return; // And presumably still optimizable()
} else if (AstSel* const subselp = VN_CAST(selp->lhsp(), Sel)) { } else if (AstSel* const subselp = VN_CAST(selp->fromp(), Sel)) {
V3Number sublsb{nodep}; V3Number sublsb{nodep};
handleAssignSelRecurse(nodep, subselp, outVarrefpRef, sublsb /*ref*/, depth + 1); handleAssignSelRecurse(nodep, subselp, outVarrefpRef, sublsb /*ref*/, depth + 1);
if (optimizable()) { if (optimizable()) {

View File

@ -148,7 +148,7 @@ class SliceVisitor final : public VNVisitor {
if (AstSliceSel* const slicep = VN_CAST(itemp, SliceSel)) { if (AstSliceSel* const slicep = VN_CAST(itemp, SliceSel)) {
offset += slicep->declRange().lo(); offset += slicep->declRange().lo();
newp = new AstArraySel{nodep->fileline(), newp = new AstArraySel{nodep->fileline(),
slicep->lhsp()->cloneTreePure(false), offset}; slicep->fromp()->cloneTreePure(false), offset};
} else { } else {
newp = new AstArraySel{nodep->fileline(), itemp->cloneTreePure(false), newp = new AstArraySel{nodep->fileline(), itemp->cloneTreePure(false),
offset}; offset};

View File

@ -267,9 +267,9 @@ private:
} }
} }
} else if (const AstWordSel* const wordp = VN_CAST(nodep->lhsp(), WordSel)) { } else if (const AstWordSel* const wordp = VN_CAST(nodep->lhsp(), WordSel)) {
if (AstVarRef* const varrefp = VN_CAST(wordp->lhsp(), VarRef)) { if (AstVarRef* const varrefp = VN_CAST(wordp->fromp(), VarRef)) {
if (VN_IS(wordp->rhsp(), Const) && isSubstVar(varrefp->varp())) { if (VN_IS(wordp->bitp(), Const) && isSubstVar(varrefp->varp())) {
const int word = VN_AS(wordp->rhsp(), Const)->toUInt(); const int word = VN_AS(wordp->bitp(), Const)->toUInt();
SubstVarEntry* const entryp = getEntryp(varrefp); SubstVarEntry* const entryp = getEntryp(varrefp);
hit = true; hit = true;
if (m_ops > SUBST_MAX_OPS_SUBST) { if (m_ops > SUBST_MAX_OPS_SUBST) {
@ -297,9 +297,9 @@ private:
} }
void visit(AstWordSel* nodep) override { void visit(AstWordSel* nodep) override {
if (!m_funcp) return; if (!m_funcp) return;
iterate(nodep->rhsp()); iterate(nodep->bitp());
AstVarRef* const varrefp = VN_CAST(nodep->lhsp(), VarRef); AstVarRef* const varrefp = VN_CAST(nodep->fromp(), VarRef);
const AstConst* const constp = VN_CAST(nodep->rhsp(), Const); const AstConst* const constp = VN_CAST(nodep->bitp(), Const);
if (varrefp && isSubstVar(varrefp->varp()) && varrefp->access().isReadOnly() && constp) { if (varrefp && isSubstVar(varrefp->varp()) && varrefp->access().isReadOnly() && constp) {
// Nicely formed lvalues handled in NodeAssign // Nicely formed lvalues handled in NodeAssign
// Other lvalues handled as unknown mess in AstVarRef // Other lvalues handled as unknown mess in AstVarRef
@ -318,7 +318,7 @@ private:
entryp->consumeWord(word); entryp->consumeWord(word);
} }
} else { } else {
iterate(nodep->lhsp()); iterate(nodep->fromp());
} }
} }
void visit(AstVarRef* nodep) override { void visit(AstVarRef* nodep) override {

View File

@ -730,12 +730,12 @@ private:
// LHS, RHS is self-determined // LHS, RHS is self-determined
// width: value(LHS) * width(RHS) // width: value(LHS) * width(RHS)
if (m_vup->prelim()) { if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH); iterateCheckSizedSelf(nodep, "RHS", nodep->countp(), SELF, BOTH);
V3Const::constifyParamsNoWarnEdit(nodep->rhsp()); // rhsp may change V3Const::constifyParamsNoWarnEdit(nodep->countp()); // rhsp may change
uint32_t times = 1; uint32_t times = 1;
const AstConst* const constp = VN_CAST(nodep->rhsp(), Const); const AstConst* const constp = VN_CAST(nodep->countp(), Const);
if (constp) times = constp->toUInt(); if (constp) times = constp->toUInt();
AstNodeDType* const vdtypep = m_vup->dtypeNullSkipRefp(); AstNodeDType* const vdtypep = m_vup->dtypeNullSkipRefp();
@ -746,18 +746,18 @@ private:
<< vdtypep->prettyDTypeNameQ() << vdtypep->prettyDTypeNameQ()
<< " data type"); << " data type");
} }
if (VN_IS(nodep->lhsp(), Concat)) { if (VN_IS(nodep->srcp(), Concat)) {
// Convert to concat directly, and visit(AstConst) will convert. // Convert to concat directly, and visit(AstConst) will convert.
// Don't iterate lhsp as SELF, the potential Concat below needs // Don't iterate lhsp as SELF, the potential Concat below needs
// the adtypep passed down to recognize the QueueDType // the adtypep passed down to recognize the QueueDType
userIterateAndNext(nodep->lhsp(), WidthVP{vdtypep, BOTH}.p()); userIterateAndNext(nodep->srcp(), WidthVP{vdtypep, BOTH}.p());
nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); nodep->replaceWith(nodep->srcp()->unlinkFrBack());
VL_DO_DANGLING(pushDeletep(nodep), nodep); VL_DO_DANGLING(pushDeletep(nodep), nodep);
return; return;
} else { // int a[] = {lhs} -> same as '{lhs} } else { // int a[] = {lhs} -> same as '{lhs}
auto* const newp = new AstPattern{ auto* const newp = new AstPattern{
nodep->fileline(), nodep->fileline(),
new AstPatMember{nodep->lhsp()->fileline(), nodep->lhsp()->unlinkFrBack(), new AstPatMember{nodep->srcp()->fileline(), nodep->srcp()->unlinkFrBack(),
nullptr, nullptr}}; nullptr, nullptr}};
nodep->replaceWith(newp); nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep); VL_DO_DANGLING(pushDeletep(nodep), nodep);
@ -769,11 +769,11 @@ private:
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Replication to form " nodep->v3warn(E_UNSUPPORTED, "Unsupported: Replication to form "
<< vdtypep->prettyDTypeNameQ() << " data type"); << vdtypep->prettyDTypeNameQ() << " data type");
} }
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); iterateCheckSizedSelf(nodep, "LHS", nodep->srcp(), SELF, BOTH);
if ((vdtypep && vdtypep->isString()) || nodep->lhsp()->isString()) { if ((vdtypep && vdtypep->isString()) || nodep->srcp()->isString()) {
AstNode* const newp AstNode* const newp
= new AstReplicateN{nodep->fileline(), nodep->lhsp()->unlinkFrBack(), = new AstReplicateN{nodep->fileline(), nodep->srcp()->unlinkFrBack(),
nodep->rhsp()->unlinkFrBack()}; nodep->countp()->unlinkFrBack()};
nodep->replaceWith(newp); nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep); VL_DO_DANGLING(pushDeletep(nodep), nodep);
return; return;
@ -785,8 +785,8 @@ private:
" (IEEE 1800-2017 11.4.12.1)"); " (IEEE 1800-2017 11.4.12.1)");
times = 1; // Set to 1, so we can continue looking for errors times = 1; // Set to 1, so we can continue looking for errors
} }
nodep->dtypeSetLogicUnsized((nodep->lhsp()->width() * times), nodep->dtypeSetLogicUnsized((nodep->srcp()->width() * times),
(nodep->lhsp()->widthMin() * times), (nodep->srcp()->widthMin() * times),
VSigning::UNSIGNED); VSigning::UNSIGNED);
} }
} }
@ -898,7 +898,7 @@ private:
userIterateAndNext(nodep->lsbp(), WidthVP{SELF, PRELIM}.p()); userIterateAndNext(nodep->lsbp(), WidthVP{SELF, PRELIM}.p());
checkCvtUS(nodep->fromp()); checkCvtUS(nodep->fromp());
iterateCheckSizedSelf(nodep, "Select Width", nodep->widthp(), SELF, BOTH); iterateCheckSizedSelf(nodep, "Select Width", nodep->widthp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "Select LHS", nodep->lhsp(), SELF, BOTH); iterateCheckSizedSelf(nodep, "Select LHS", nodep->fromp(), SELF, BOTH);
V3Const::constifyParamsEdit(nodep->widthp()); // widthp may change V3Const::constifyParamsEdit(nodep->widthp()); // widthp may change
const AstConst* const widthConstp = VN_CAST(nodep->widthp(), Const); const AstConst* const widthConstp = VN_CAST(nodep->widthp(), Const);
if (!widthConstp) { if (!widthConstp) {
@ -1141,7 +1141,7 @@ private:
void visit(AstSelBit* nodep) override { void visit(AstSelBit* nodep) override {
// Just a quick check as after V3Param these nodes instead are AstSel's // Just a quick check as after V3Param these nodes instead are AstSel's
userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->bitp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->thsp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->thsp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->attrp(), WidthVP{SELF, BOTH}.p()); userIterateAndNext(nodep->attrp(), WidthVP{SELF, BOTH}.p());
AstNode* const selp = V3Width::widthSelNoIterEdit(nodep); AstNode* const selp = V3Width::widthSelNoIterEdit(nodep);
@ -1155,8 +1155,8 @@ private:
void visit(AstSelExtract* nodep) override { void visit(AstSelExtract* nodep) override {
// Just a quick check as after V3Param these nodes instead are AstSel's // Just a quick check as after V3Param these nodes instead are AstSel's
userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->leftp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->thsp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->rightp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->attrp(), WidthVP{SELF, BOTH}.p()); userIterateAndNext(nodep->attrp(), WidthVP{SELF, BOTH}.p());
AstNode* const selp = V3Width::widthSelNoIterEdit(nodep); AstNode* const selp = V3Width::widthSelNoIterEdit(nodep);
if (selp != nodep) { if (selp != nodep) {
@ -1168,8 +1168,8 @@ private:
} }
void visit(AstSelPlus* nodep) override { void visit(AstSelPlus* nodep) override {
userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->bitp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->thsp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->widthp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->attrp(), WidthVP{SELF, BOTH}.p()); userIterateAndNext(nodep->attrp(), WidthVP{SELF, BOTH}.p());
AstNode* const selp = V3Width::widthSelNoIterEdit(nodep); AstNode* const selp = V3Width::widthSelNoIterEdit(nodep);
if (selp != nodep) { if (selp != nodep) {
@ -1181,8 +1181,8 @@ private:
} }
void visit(AstSelMinus* nodep) override { void visit(AstSelMinus* nodep) override {
userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->bitp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->thsp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel userIterateAndNext(nodep->widthp(), WidthVP{CONTEXT_DET, PRELIM}.p()); // FINAL in AstSel
userIterateAndNext(nodep->attrp(), WidthVP{SELF, BOTH}.p()); userIterateAndNext(nodep->attrp(), WidthVP{SELF, BOTH}.p());
AstNode* const selp = V3Width::widthSelNoIterEdit(nodep); AstNode* const selp = V3Width::widthSelNoIterEdit(nodep);
if (selp != nodep) { if (selp != nodep) {

View File

@ -216,7 +216,7 @@ private:
if (debug() >= 9) nodep->backp()->dumpTree("- SELBT0: "); if (debug() >= 9) nodep->backp()->dumpTree("- SELBT0: ");
// lhsp/rhsp do not need to be constant // lhsp/rhsp do not need to be constant
AstNodeExpr* const fromp = nodep->fromp()->unlinkFrBack(); AstNodeExpr* const fromp = nodep->fromp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack(); // bit we're extracting AstNodeExpr* const rhsp = nodep->bitp()->unlinkFrBack(); // bit we're extracting
if (debug() >= 9) nodep->dumpTree("- SELBT2: "); if (debug() >= 9) nodep->dumpTree("- SELBT2: ");
const FromData fromdata = fromDataForArray(nodep, fromp); const FromData fromdata = fromDataForArray(nodep, fromp);
AstNodeDType* const ddtypep = fromdata.m_dtypep; AstNodeDType* const ddtypep = fromdata.m_dtypep;
@ -354,8 +354,8 @@ private:
AstNodeDType* const ddtypep = fromdata.m_dtypep; AstNodeDType* const ddtypep = fromdata.m_dtypep;
const VNumRange fromRange = fromdata.m_fromRange; const VNumRange fromRange = fromdata.m_fromRange;
if (VN_IS(ddtypep, QueueDType)) { if (VN_IS(ddtypep, QueueDType)) {
AstNodeExpr* const qleftp = nodep->rhsp()->unlinkFrBack(); AstNodeExpr* const qleftp = nodep->leftp()->unlinkFrBack();
AstNodeExpr* const qrightp = nodep->thsp()->unlinkFrBack(); AstNodeExpr* const qrightp = nodep->rightp()->unlinkFrBack();
AstNodeExpr* const qleftBacknessp = selQueueBackness(qleftp); AstNodeExpr* const qleftBacknessp = selQueueBackness(qleftp);
AstNodeExpr* const qrightBacknessp = selQueueBackness(qrightp); AstNodeExpr* const qrightBacknessp = selQueueBackness(qrightp);
// Use special methods to refer to back rather than math using // Use special methods to refer to back rather than math using
@ -381,8 +381,8 @@ private:
"First value of [a:b] isn't a constant, maybe you want +: or -:"); "First value of [a:b] isn't a constant, maybe you want +: or -:");
checkConstantOrReplace(nodep->rightp(), checkConstantOrReplace(nodep->rightp(),
"Second value of [a:b] isn't a constant, maybe you want +: or -:"); "Second value of [a:b] isn't a constant, maybe you want +: or -:");
AstNodeExpr* const msbp = nodep->rhsp()->unlinkFrBack(); AstNodeExpr* const msbp = nodep->leftp()->unlinkFrBack();
AstNodeExpr* const lsbp = nodep->thsp()->unlinkFrBack(); AstNodeExpr* const lsbp = nodep->rightp()->unlinkFrBack();
int32_t msb = VN_AS(msbp, Const)->toSInt(); int32_t msb = VN_AS(msbp, Const)->toSInt();
int32_t lsb = VN_AS(lsbp, Const)->toSInt(); int32_t lsb = VN_AS(lsbp, Const)->toSInt();
const int32_t elem = (msb > lsb) ? (msb - lsb + 1) : (lsb - msb + 1); const int32_t elem = (msb > lsb) ? (msb - lsb + 1) : (lsb - msb + 1);

View File

@ -503,13 +503,16 @@ class Cpt:
" // Generated by astgen with short-circuiting\n" + " // Generated by astgen with short-circuiting\n" +
" void visit(Ast" + node.name + " void visit(Ast" + node.name +
"* nodep) override {\n" + "* nodep) override {\n" +
" iterateAndNextNull(nodep->lhsp());\n" + " iterateAndNextNull(nodep->{op1}());\n".format(
"".join(out_for_type_sc)) op1=node.getOp(1)[0]) + "".join(out_for_type_sc))
if out_for_type[0]: if out_for_type[0]:
self.print(" iterateAndNextNull(nodep->rhsp());\n") self.print(
" iterateAndNextNull(nodep->{op2}());\n".format(
op2=node.getOp(2)[0]))
if node.isSubClassOf(AstNodes["NodeTriop"]): if node.isSubClassOf(AstNodes["NodeTriop"]):
self.print( self.print(
" iterateAndNextNull(nodep->thsp());\n") " iterateAndNextNull(nodep->{op3}());\n".
format(op3=node.getOp(3)[0]))
self.print("".join(out_for_type) + " }\n") self.print("".join(out_for_type) + " }\n")
elif len(out_for_type) > 0: # Other types with something to print elif len(out_for_type) > 0: # Other types with something to print
skip = node.name in self.tree_skip_visit skip = node.name in self.tree_skip_visit
@ -976,6 +979,8 @@ def write_ast_macros(filename):
''', ''',
t=node.name) t=node.name)
hiddenMethods = []
for n in range(1, 5): for n in range(1, 5):
op = node.getOp(n) op = node.getOp(n)
if not op: if not op:
@ -983,6 +988,11 @@ def write_ast_macros(filename):
name, monad, kind = op name, monad, kind = op
retrieve = ("VN_DBG_AS(op{n}p(), {kind})" if kind != "Node" retrieve = ("VN_DBG_AS(op{n}p(), {kind})" if kind != "Node"
else "op{n}p()").format(n=n, kind=kind) else "op{n}p()").format(n=n, kind=kind)
superOp = node.superClass.getOp(n)
superName = None
if superOp:
superName = superOp[0]
hiddenMethods.append(superName)
if monad == "List": if monad == "List":
emitBlock('''\ emitBlock('''\
Ast{kind}* {name}() const VL_MT_STABLE {{ return {retrieve}; }} Ast{kind}* {name}() const VL_MT_STABLE {{ return {retrieve}; }}
@ -993,6 +1003,9 @@ def write_ast_macros(filename):
Name=name[0].upper() + name[1:], Name=name[0].upper() + name[1:],
n=n, n=n,
retrieve=retrieve) retrieve=retrieve)
if superOp:
hiddenMethods.append("add" + superName[0].upper() +
superName[1:])
elif monad == "Optional": elif monad == "Optional":
emitBlock('''\ emitBlock('''\
Ast{kind}* {name}() const VL_MT_STABLE {{ return {retrieve}; }} Ast{kind}* {name}() const VL_MT_STABLE {{ return {retrieve}; }}
@ -1012,6 +1025,13 @@ def write_ast_macros(filename):
n=n, n=n,
retrieve=retrieve) retrieve=retrieve)
if hiddenMethods:
fh.write("private: \\\n")
for method in hiddenMethods:
fh.write(" using Ast{sup}::{method}; \\\n".format(
sup=node.superClass.name, method=method))
fh.write("public: \\\n")
fh.write( fh.write(
" static_assert(true, \"\")\n") # Swallowing the semicolon " static_assert(true, \"\")\n") # Swallowing the semicolon