Internals: Make AstCAwait an AstNodeStmt (#6280) (#7078)

AstCAwait is only ever uses in statement position, so model it as a
statement. We should never ever have a coroutine that returns a value.
There is no need for it in SV, nor should we rely on it for internals.

Also reworks the fix for V3Life incorrectly constant propagating the
beforeTrig functions (#7072). The property that upsets V3Life is that
a function:
1. Is called from multiple static call sites (multiple AstCCall)
2. Reads model state directly (AstVarRef to non-locals/arguments)

Such function can only be created internally after scheduling (V3Task
throws an unsupported error on a non-inlined function that reads model
state), so added a flag to AstCFunc to mark the dangerous ones for
V3Life.
This commit is contained in:
Geza Lore
2026-02-14 20:15:32 +00:00
committed by GitHub
parent be27811a10
commit a0b89dde8e
9 changed files with 53 additions and 64 deletions
+4 -6
View File
@@ -137,11 +137,11 @@ void splitCheckFinishSubFunc(AstCFunc* ofuncp, AstCFunc* subFuncp,
}
bool containsAwait = false;
subFuncp->foreach([&](AstNodeExpr* exprp) {
subFuncp->foreach([&](AstNode* nodep) {
// Record if it has a CAwait
if (VN_IS(exprp, CAwait)) containsAwait = true;
if (VN_IS(nodep, CAwait)) containsAwait = true;
// Redirect references to arguments to the clone in the sub-function
if (AstVarRef* const refp = VN_CAST(exprp, VarRef)) {
if (AstVarRef* const refp = VN_CAST(nodep, VarRef)) {
if (AstVarScope* const vscp = VN_AS(refp->varp()->user3p(), VarScope)) {
refp->varp(vscp->varp());
refp->varScopep(vscp);
@@ -151,9 +151,7 @@ void splitCheckFinishSubFunc(AstCFunc* ofuncp, AstCFunc* subFuncp,
if (ofuncp->isCoroutine() && containsAwait) { // Wrap call with co_await
subFuncp->rtnType("VlCoroutine");
AstCAwait* const awaitp = new AstCAwait{flp, callp};
awaitp->dtypeSetVoid();
ofuncp->addStmtsp(awaitp->makeStmt());
ofuncp->addStmtsp(new AstCAwait{flp, callp});
} else {
ofuncp->addStmtsp(callp->makeStmt());
}