-
Notifications
You must be signed in to change notification settings - Fork 685
Make node iteration stricter #4617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -887,7 +887,7 @@ class ConstVisitor final : public VNVisitor { | |
// ** must track down everywhere V3Const is called and make sure no overlaps. | ||
// AstVar::user4p -> Used by variable marking/finding | ||
// AstJumpLabel::user4 -> bool. Set when AstJumpGo uses this label | ||
// AstEnum::user4 -> bool. Recursing. | ||
// AstEnumItem::user4 -> bool. Already checked for self references | ||
|
||
// STATE | ||
static constexpr bool m_doShort = true; // Remove expressions that short circuit | ||
|
@@ -2744,26 +2744,29 @@ class ConstVisitor final : public VNVisitor { | |
} | ||
void visit(AstEnumItemRef* nodep) override { | ||
iterateChildren(nodep); | ||
UASSERT_OBJ(nodep->itemp(), nodep, "Not linked"); | ||
bool did = false; | ||
if (nodep->itemp()->valuep()) { | ||
// if (debug()) nodep->itemp()->valuep()->dumpTree("- visitvaref: "); | ||
if (nodep->itemp()->user4()) { | ||
nodep->v3error("Recursive enum value: " << nodep->itemp()->prettyNameQ()); | ||
AstEnumItem* const itemp = nodep->itemp(); | ||
UASSERT_OBJ(itemp, nodep, "Not linked"); | ||
if (!itemp->user4SetOnce() && itemp->valuep()) { | ||
// Check for recursive self references (this should really not be here..) | ||
const bool isRecursive = itemp->valuep()->exists([&](AstEnumItemRef* refp) { // | ||
return refp->itemp() == itemp; | ||
}); | ||
if (isRecursive) { | ||
nodep->v3error("Recursive enum value: " << itemp->prettyNameQ()); | ||
} else { | ||
nodep->itemp()->user4(true); | ||
iterateAndNextNull(nodep->itemp()->valuep()); | ||
nodep->itemp()->user4(false); | ||
} | ||
if (AstConst* const valuep = VN_CAST(nodep->itemp()->valuep(), Const)) { | ||
const V3Number& num = valuep->num(); | ||
VL_DO_DANGLING(replaceNum(nodep, num), nodep); | ||
did = true; | ||
// Simplify the value | ||
iterate(itemp->valuep()); | ||
Comment on lines
+2757
to
+2758
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may change itemp, so you shouldn't record itemp in a variable. (Generally true throughout V3Width - avoid remembering node pointers across iterate.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is V3Const, and we are iterating the the child node valuep(), not itemp? In this case, we know itemp is not changed as it is an AstEnumItem, which should not ever be changed, only it's childern (the enum vlaue)? |
||
} | ||
} | ||
bool did = false; | ||
if (AstConst* const valuep = VN_CAST(itemp->valuep(), Const)) { | ||
const V3Number& num = valuep->num(); | ||
VL_DO_DANGLING(replaceNum(nodep, num), nodep); | ||
did = true; | ||
} | ||
if (!did && m_required) { | ||
nodep->v3error("Expecting expression to be constant, but enum value isn't const: " | ||
<< nodep->itemp()->prettyNameQ()); | ||
<< itemp->prettyNameQ()); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2094,16 +2094,20 @@ class WidthVisitor final : public VNVisitor { | |
// We can't skip this step when width()!=0, as creating a AstVar | ||
// with non-constant range gets size 1, not size 0. So use didWidth(). | ||
if (nodep->didWidth()) return; | ||
if (nodep->doingWidth()) { // Early exit if have circular parameter definition | ||
UASSERT_OBJ(nodep->valuep(), nodep, "circular, but without value"); | ||
nodep->doingWidth(true); | ||
|
||
// Check for recursive initialization | ||
std::function<bool(AstNode*)> isRecursive = [&](AstNode* np) -> bool { | ||
return np && np->exists([&](AstNodeVarRef* refp) { | ||
return refp->varp() == nodep || isRecursive(refp->varp()->valuep()); | ||
}); | ||
}; | ||
Comment on lines
+2100
to
+2104
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I preferred the old form as if we ever have another way to get to the var twice it will detect, and also IMO was easier to understand. Was this needed to prevent a new assertion? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is needed because of the assertions: you can't call iterateAndNext on the same node twice (recursively). Doing so was never really safe to do due to the later call stomping m_iterpp hence edits in the higher call would have been borked. |
||
if (isRecursive(nodep->valuep())) { | ||
nodep->v3error("Variable's initial value is circular: " << nodep->prettyNameQ()); | ||
pushDeletep(nodep->valuep()->unlinkFrBack()); | ||
nodep->valuep(new AstConst{nodep->fileline(), AstConst::BitTrue{}}); | ||
nodep->dtypeFrom(nodep->valuep()); | ||
nodep->didWidth(true); | ||
return; | ||
} | ||
nodep->doingWidth(true); | ||
|
||
// Make sure dtype is sized | ||
nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); | ||
UASSERT_OBJ(nodep->dtypep(), nodep, "No dtype determined for var"); | ||
|
Uh oh!
There was an error while loading. Please reload this page.