From 4de1b226721f53e7b4e98b0c6694e0bd66652eb6 Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Mon, 17 Jul 2023 13:30:42 +0200 Subject: [PATCH] Fix handling of super.new calls (#4366) --- src/V3EmitCFunc.h | 39 ++++++++++++++++++------------ test_regress/t/t_class_super_new.v | 15 ++++++++++++ 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index e2f4564a7..ba7c10e54 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -234,6 +234,21 @@ public: string optionalProcArg(const T* const nodep) { return (nodep && constructorNeedsProcess(nodep)) ? "vlProcess, " : ""; } + const AstCNew* getSuperNewCallRecursep(AstNode* const nodep) { + // Get the super.new call + if (!nodep) return nullptr; + if (const AstCNew* const cnewp = VN_CAST(nodep, CNew)) return cnewp; + if (const AstStmtExpr* const stmtp = VN_CAST(nodep, StmtExpr)) { + if (const AstCNew* const cnewp = VN_CAST(stmtp->exprp(), CNew)) return cnewp; + } + if (const AstJumpBlock* const blockp = VN_CAST(nodep, JumpBlock)) { + if (const AstCNew* const cnewp = getSuperNewCallRecursep(blockp->stmtsp())) { + return cnewp; + } + } + if (const AstCNew* const cnewp = getSuperNewCallRecursep(nodep->nextp())) return cnewp; + return nullptr; + } // VISITORS using EmitCConstInit::visit; @@ -256,24 +271,16 @@ public: puts(": "); puts(nodep->baseCtors()); const AstClass* const classp = VN_CAST(nodep->scopep()->modp(), Class); - bool baseCtorCall = false; // Find call to super.new to get the arguments - for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { - AstNode* exprp; - if (VN_IS(stmtp, StmtExpr)) { - exprp = VN_CAST(stmtp, StmtExpr)->exprp(); - } else { - exprp = stmtp; - } - if (AstCNew* const newRefp = VN_CAST(exprp, CNew)) { - puts("(" + optionalProcArg(classp) + "vlSymsp"); - baseCtorCall = true; - putCommaIterateNext(newRefp->argsp(), true); - puts(")"); - break; - } + if (classp && constructorNeedsProcess(classp)) { + puts("(vlProcess, vlSymsp"); + } else { + puts("(vlSymsp"); } - if (!baseCtorCall) { puts("(" + optionalProcArg(classp) + "vlSymsp)"); } + const AstCNew* const superNewCallp = getSuperNewCallRecursep(nodep->stmtsp()); + UASSERT_OBJ(superNewCallp, nodep, "super.new call not found"); + putCommaIterateNext(superNewCallp->argsp(), true); + puts(")"); } puts(" {\n"); diff --git a/test_regress/t/t_class_super_new.v b/test_regress/t/t_class_super_new.v index 1358a46c6..58fe8bc3b 100644 --- a/test_regress/t/t_class_super_new.v +++ b/test_regress/t/t_class_super_new.v @@ -39,6 +39,16 @@ class BarArg extends FooArg; endfunction endclass +class BarArgWithReturnInIf extends FooArg; + function new (int a); + super.new(a); + if (a < 10) begin + return; + end + this.x = 20; + endfunction +endclass + class BarExpr extends FooArg; function new (int a, string b); super.new(a + b.len()); @@ -114,6 +124,7 @@ module t (/*AUTOARG*/ NewWithoutSuper newWithoutSuper; NoNewParam#(2) noNewParam; NewWithoutSuperParam#(1) newWithoutSuperParam; + BarArgWithReturnInIf barIf1, barIf10; initial begin bar = new; @@ -136,6 +147,10 @@ module t (/*AUTOARG*/ `checkh(noNewParam.x, 1); newWithoutSuperParam = new; `checkh(newWithoutSuperParam.x, 1); + barIf1 = new(1); + `checkh(barIf1.x, 1); + barIf10 = new(10); + `checkh(barIf10.x, 20); $write("*-* All Finished *-*\n"); $finish;