Removal of contructors for interface classes

Signed-off-by: Igor Zaworski <izaworski@internships.antmicro.com>
This commit is contained in:
Igor Zaworski 2026-01-20 16:59:12 +01:00
parent 764e1d53d4
commit 5f3a0725fc
5 changed files with 27 additions and 15 deletions

View File

@ -149,6 +149,10 @@ class CCtorsVisitor final : public VNVisitor {
// VISITORS
void visit(AstNodeModule* nodep) override {
if (const AstClass* const classp = VN_CAST(nodep, Class)) {
// Interface class may only have pure virtuals and params which do not need cctor reset
if (classp->isInterfaceClass()) return;
}
VL_RESTORER(m_modp);
VL_RESTORER(m_varResetp);
m_modp = nodep;

View File

@ -143,11 +143,12 @@ void EmitCBaseVisitorConst::emitCFuncHeader(const AstCFunc* funcp, const AstNode
if (funcp->isConstructor()) {
if (!withScope) putns(funcp, funcNameProtect(funcp, modp));
if (!withScope) {
puts("() = default;\n");
puts("() = default");
if (const AstClass* const classp = VN_CAST(modp, Class)) {
if (classp->isInterfaceClass()) puts("bool __VvirtClassInitialized = false;\n");
// Interfaces classes do not need a constructor
if (classp->isInterfaceClass()) return;
}
puts("void ");
puts(";\nvoid ");
}
puts("init");
} else {
@ -168,7 +169,9 @@ void EmitCBaseVisitorConst::emitCFuncDecl(const AstCFunc* funcp, const AstNodeMo
putns(funcp, "virtual ");
}
emitCFuncHeader(funcp, modp, /* withScope: */ false);
if (funcp->emptyBody() && !funcp->isLoose() && !cLinkage) {
const AstClass* const classp = VN_CAST(modp, Class);
if (funcp->emptyBody() && !funcp->isLoose() && !cLinkage
&& !(funcp->isConstructor() && classp && classp->isInterfaceClass())) {
putns(funcp, " {}\n");
} else {
putns(funcp, ";\n");

View File

@ -335,6 +335,7 @@ public:
std::unordered_set<AstClass*> doneClasses;
collectVirtualBasesRecursep(classp, virtualBases);
for (AstClass* vbase : virtualBases) {
if (vbase->isInterfaceClass()) continue;
if (doneClasses.count(vbase)) continue;
doneClasses.emplace(vbase);
puts(EmitCUtil::prefixNameProtect(vbase));
@ -350,6 +351,7 @@ public:
// Direct non-virtual bases in declaration order
for (const AstClassExtends* extp = classp->extendsp(); extp;
extp = VN_AS(extp->nextp(), ClassExtends)) {
if (extp->classp()->isInterfaceClass()) continue;
if (extp->classp()->useVirtualPublic()) continue;
if (doneClasses.count(extp->classp())) continue;
doneClasses.emplace(extp->classp());
@ -406,13 +408,7 @@ public:
puts(" {\n");
if (nodep->isConstructor()) {
const AstClass* const classp = VN_CAST(nodep->scopep()->modp(), Class);
if (classp && classp->extendsp()) {
if (classp->isInterfaceClass()) {
puts("if (__VvirtClassInitialized) return;\n");
puts("__VvirtClassInitialized = true;\n");
}
putConstructorSubinit(classp, nodep);
}
if (classp && classp->extendsp()) putConstructorSubinit(classp, nodep);
}
// "+" in the debug indicates a print from the model

View File

@ -5288,7 +5288,10 @@ class LinkDotResolveVisitor final : public VNVisitor {
<< classExtendsp->argsp()->warnContextSecondary());
}
if (classExtendsp && classExtendsp->classOrNullp()) {
if (!m_explicitSuperNewp && m_statep->forParamed()) {
if (!m_explicitSuperNewp && m_statep->forParamed()
&& !VN_AS(classExtendsp->childDTypep()->skipRefp(), ClassRefDType)
->classp()
->isInterfaceClass()) {
AstNodeStmt* const superNewp
= addImplicitSuperNewCall(VN_AS(nodep, Func), classExtendsp);
UINFO(9, "created super new " << superNewp);

View File

@ -1310,9 +1310,15 @@ class TaskVisitor final : public VNVisitor {
if (!nodep->dpiImport() && !nodep->taskPublic()) {
// Need symbol table
if (cfuncp->name() == "new") {
const string stmt = VIdProtect::protect("_ctor_var_reset") + "(vlSymsp);";
cfuncp->addStmtsp(new AstCStmt{nodep->fileline(), stmt});
if (cfuncp->isConstructor()) {
bool isInterfaceClass = false;
if (const AstClass* const classp = VN_CAST(m_modp, Class)) {
isInterfaceClass = classp->isInterfaceClass();
}
if (!isInterfaceClass) {
const string stmt = VIdProtect::protect("_ctor_var_reset") + "(vlSymsp);";
cfuncp->addStmtsp(new AstCStmt{nodep->fileline(), stmt});
}
}
}
if (nodep->dpiContext()) {