Fix copy constructor of classes with constraints (#8381)

This commit is contained in:
Ryszard Rozak
2026-09-18 07:47:25 -04:00
committed by GitHub
parent 5f38b797f3
commit c25f287779
10 changed files with 537 additions and 15 deletions
+44 -3
View File
@@ -4583,6 +4583,43 @@ class RandomizeVisitor final : public VNVisitor {
return resExprp;
}
void addUpdateRandVarsBody(AstClass* const nodep, AstFunc* const randomizep) {
UASSERT_OBJ(!nodep->hasRandVarsUpdate(), nodep, "__VupdateRandVars already exists");
AstFunc* const updatep
= new AstFunc{nodep->fileline(), "__VupdateRandVars", nullptr, nullptr};
updatep->classMethod(true);
updatep->isVirtual(true);
updatep->keepAlive(true);
updatep->needsSyms(false);
nodep->addMembersp(updatep);
nodep->hasRandVarsUpdate(true);
for (AstClass* classp = nodep; classp;
classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr) {
AstNodeFTask* const newp = VN_AS(m_memberMap.findMember(classp, "new"), NodeFTask);
for (AstNode* stmtp = newp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
AstStmtExpr* const stmtExprp = VN_CAST(stmtp, StmtExpr);
if (!stmtExprp) continue;
AstCMethodHard* const methodp = VN_CAST(stmtExprp->exprp(), CMethodHard);
if (!methodp || methodp->method() != VCMethod::RANDOMIZER_WRITE_VAR) continue;
AstNodeVarRef* const varRefp = VN_AS(methodp->pinsp(), NodeVarRef);
if (varRefp->varp()->lifetime().isStatic()) {
// There is no need to update pointer to a static variable
continue;
}
AstCMethodHard* const updateMethodp = new AstCMethodHard{
methodp->fileline(), methodp->fromp()->cloneTreePure(false),
VCMethod::RANDOMIZER_UPDATE_VAR, varRefp->cloneTreePure(false)};
updateMethodp->dtypeSetVoid();
AstNodeExpr* const namep = VN_AS(varRefp->nextp()->nextp(), NodeExpr);
updateMethodp->addPinsp(namep->cloneTreePure(false));
updateMethodp->method(VCMethod::RANDOMIZER_UPDATE_VAR);
updatep->addStmtsp(updateMethodp->makeStmt());
}
}
}
void addBasicRandomizeBody(AstFunc* const basicRandomizep, AstClass* const nodep,
AstVar* randModeVarp) {
UINFO(9, "addBasicRTB " << nodep);
@@ -5782,6 +5819,8 @@ class RandomizeVisitor final : public VNVisitor {
beginValp = new AstConst{fl, AstConst::WidthedValue{}, 32, 1};
}
addUpdateRandVarsBody(nodep, randomizep);
AstFunc* const basicRandomizep
= V3Randomize::newRandomizeFunc(m_memberMap, nodep, BASIC_RANDOMIZE_FUNC_NAME);
addBasicRandomizeBody(basicRandomizep, nodep, randModeVarp);
@@ -6337,9 +6376,10 @@ class RandomizeVisitor final : public VNVisitor {
= newResizeConstrainedArrayTask(classp, m_constraintp->name());
m_constraintp->user3p(resizerTaskp);
}
AstVarRef* const sizeVarRefp = new AstVarRef{
fl, VN_AS(sizeVarp->user2p(), NodeModule), sizeVarp, VAccess::READ};
AstCMethodHard* const resizep = new AstCMethodHard{
fl, nodep->fromp()->unlinkFrBack(), VCMethod::DYN_RESIZE,
new AstVarRef{fl, sizeVarp, VAccess::READ}};
fl, nodep->fromp()->unlinkFrBack(), VCMethod::DYN_RESIZE, sizeVarRefp};
resizep->dtypep(nodep->findVoidDType());
resizerTaskp->addStmtsp(new AstStmtExpr{fl, resizep});
}
@@ -6348,7 +6388,8 @@ class RandomizeVisitor final : public VNVisitor {
// to make sure it is always >= 0.
m_constraintp->addItemsp(createSizeGteZeroConstraint(fl, sizeVarp));
}
AstVarRef* const sizeVarRefp = new AstVarRef{fl, sizeVarp, VAccess::READ};
AstVarRef* const sizeVarRefp = new AstVarRef{fl, VN_AS(sizeVarp->user2p(), NodeModule),
sizeVarp, VAccess::READ};
sizeVarRefp->user1(true);
nodep->replaceWith(sizeVarRefp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);