Internals: Fix fallout from #6588

This commit is contained in:
Geza Lore 2025-10-26 08:48:26 +00:00
parent 7225c902ee
commit bfb20397d9
1 changed files with 65 additions and 45 deletions

View File

@ -360,45 +360,71 @@ void transformForks(AstNetlist* const netlistp) {
// Replace self with the function calls (no co_await, as we don't want the main // Replace self with the function calls (no co_await, as we don't want the main
// process to suspend whenever any of the children do) // process to suspend whenever any of the children do)
// V3Dead could have removed all statements from the fork, so guard against it // V3Dead could have removed all statements from the fork, so guard against it
if (nodep->forksp()) nodep->addNextHere(nodep->forksp()->unlinkFrBackWithNext()); // Inline begins now that they are not needed
if (nodep->stmtsp()) nodep->addNextHere(nodep->stmtsp()->unlinkFrBackWithNext()); AstNode* resp = nullptr;
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); if (AstNode* const declsp = nodep->declsp()) {
resp = AstNode::addNext(resp, declsp->unlinkFrBackWithNext());
}
if (AstNode* const stmtsp = nodep->stmtsp()) {
resp = AstNode::addNext(resp, stmtsp->unlinkFrBackWithNext());
}
while (AstBegin* const beginp = nodep->forksp()) {
if (AstNode* const declsp = beginp->declsp()) {
resp = AstNode::addNext(resp, declsp->unlinkFrBackWithNext());
}
if (AstNode* const stmtsp = beginp->stmtsp()) {
resp = AstNode::addNext(resp, stmtsp->unlinkFrBackWithNext());
}
VL_DO_DANGLING(pushDeletep(beginp->unlinkFrBack()), beginp);
}
if (resp) {
nodep->replaceWith(resp);
} else {
nodep->unlinkFrBack();
}
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} }
void visit(AstBegin* nodep) override { void visit(AstBegin* nodep) override {
UASSERT_OBJ(m_forkp, nodep, "Begin outside of a fork"); UASSERT_OBJ(m_forkp, nodep, "Begin outside of a fork");
// Start with children, so later we only find awaits that are actually in this begin // Start with children, so later we only find awaits that are actually in this begin
m_beginHasAwaits = false; m_beginHasAwaits = false;
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
if (!nodep->stmtsp()) { if (!nodep->stmtsp()) return;
nodep->unlinkFrBack(); if (!m_beginHasAwaits && !nodep->needProcess()) return;
} else if (m_beginHasAwaits || nodep->needProcess()) {
UASSERT_OBJ(!nodep->name().empty(), nodep, "Begin needs a name"); UASSERT_OBJ(!nodep->name().empty(), nodep, "Begin needs a name");
// Create a function to put this begin's statements in // Create a function to put this begin's statements in
FileLine* const flp = nodep->fileline(); FileLine* const flp = nodep->fileline();
AstCFunc* const newfuncp = new AstCFunc{ AstCFunc* const newfuncp = new AstCFunc{flp, m_funcp->name() + "__" + nodep->name(),
flp, m_funcp->name() + "__" + nodep->name(), m_funcp->scopep(), "VlCoroutine"}; m_funcp->scopep(), "VlCoroutine"};
m_funcp->addNextHere(newfuncp); m_funcp->addNextHere(newfuncp);
newfuncp->isLoose(m_funcp->isLoose()); newfuncp->isLoose(m_funcp->isLoose());
newfuncp->slow(m_funcp->slow()); newfuncp->slow(m_funcp->slow());
newfuncp->isConst(m_funcp->isConst()); newfuncp->isConst(m_funcp->isConst());
newfuncp->declPrivate(true); newfuncp->declPrivate(true);
// Replace the begin with a call to the newly created function // Create the call to the function
AstCCall* const callp = new AstCCall{flp, newfuncp}; AstCCall* const callp = new AstCCall{flp, newfuncp};
callp->dtypeSetVoid(); callp->dtypeSetVoid();
nodep->replaceWith(callp->makeStmt());
// If we're in a class, add a vlSymsp arg // If we're in a class, add a vlSymsp arg
if (m_inClass) { if (m_inClass) {
newfuncp->addStmtsp(new AstCStmt{flp, "VL_KEEP_THIS;"}); newfuncp->addStmtsp(new AstCStmt{flp, "VL_KEEP_THIS;"});
newfuncp->argTypes(EmitCUtil::symClassVar()); newfuncp->argTypes(EmitCUtil::symClassVar());
callp->argTypes("vlSymsp"); callp->argTypes("vlSymsp");
} }
// Put the begin's statements in the function, delete the begin // Put the begin's statements in the function
newfuncp->addStmtsp(nodep->stmtsp()->unlinkFrBackWithNext()); if (AstNode* const declsp = nodep->declsp()) {
newfuncp->addStmtsp(declsp->unlinkFrBackWithNext());
}
if (AstNode* const stmtsp = nodep->stmtsp()) {
newfuncp->addStmtsp(stmtsp->unlinkFrBackWithNext());
}
// Replace the body of the begin with a call to the newly created function
nodep->addStmtsp(callp->makeStmt());
// Propagate if needs process
if (nodep->needProcess()) { if (nodep->needProcess()) {
newfuncp->setNeedProcess(); newfuncp->setNeedProcess();
newfuncp->addStmtsp( newfuncp->addStmtsp(new AstCStmt{flp, "vlProcess->state(VlProcess::FINISHED);"});
new AstCStmt{flp, "vlProcess->state(VlProcess::FINISHED);"});
} }
if (!m_beginHasAwaits) { if (!m_beginHasAwaits) {
// co_return at the end (either that or a co_await is required in a coroutine // co_return at the end (either that or a co_await is required in a coroutine
@ -407,12 +433,6 @@ void transformForks(AstNetlist* const netlistp) {
m_awaitMoved = true; m_awaitMoved = true;
} }
remapLocals(newfuncp, callp); remapLocals(newfuncp, callp);
} else {
// The begin has neither awaits nor a process::self call, just inline the
// statements
nodep->replaceWith(nodep->stmtsp()->unlinkFrBackWithNext());
}
VL_DO_DANGLING(nodep->deleteTree(), nodep);
} }
void visit(AstCAwait* nodep) override { void visit(AstCAwait* nodep) override {
m_beginHasAwaits = true; m_beginHasAwaits = true;