Fix of localize for super constructors with function calls as arguments (#6330)
This commit is contained in:
parent
ac2a75fbb5
commit
c2cac8a7fd
|
|
@ -45,6 +45,9 @@ class LocalizeVisitor final : public VNVisitor {
|
|||
// AstVarScope::user3p() -> Set of CFuncs referencing this VarScope. (via m_accessors)
|
||||
// AstCFunc::user4p() -> Multimap of 'VarScope -> VarRefs that reference that VarScope'
|
||||
// in this function. (via m_references)
|
||||
// AstVarScope::user4() -> Bool indicating VarScope cannot be optimized
|
||||
// - compared to AstVarScope::user1 this guarantees that this
|
||||
// scope won't be optimized.
|
||||
const VNUser1InUse m_user1InUse;
|
||||
const VNUser3InUse m_user3InUse;
|
||||
const VNUser4InUse m_user4InUse;
|
||||
|
|
@ -60,11 +63,15 @@ class LocalizeVisitor final : public VNVisitor {
|
|||
// STATE - for current visit position (use VL_RESTORER)
|
||||
AstCFunc* m_cfuncp = nullptr; // Current active function
|
||||
uint32_t m_nodeDepth = 0; // Node depth under m_cfuncp
|
||||
bool m_inSuperConstructorCallStmt = false; // If under super constructor call statement
|
||||
|
||||
// METHODS
|
||||
bool isOptimizable(AstVarScope* nodep) {
|
||||
// Don't want to malloc/free the backing store all the time
|
||||
if (VN_IS(nodep->dtypep(), NBACommitQueueDType)) return false;
|
||||
// Variables used in super constructor call can't be localized, because
|
||||
// in C++ there is no way to declare them before base class constructor call
|
||||
if (nodep->user4()) return false;
|
||||
return ((!nodep->user1() // Not marked as not optimizable, or ...
|
||||
// .. a block temp used in a single CFunc
|
||||
|| (nodep->varp()->varType() == VVarType::BLOCKTEMP
|
||||
|
|
@ -147,6 +154,14 @@ class LocalizeVisitor final : public VNVisitor {
|
|||
iterateChildrenConst(nodep);
|
||||
}
|
||||
|
||||
void visit(AstCNew* nodep) override {
|
||||
VL_RESTORER(m_inSuperConstructorCallStmt);
|
||||
m_inSuperConstructorCallStmt
|
||||
= m_cfuncp->isConstructor() && VN_IS(nodep->backp(), StmtExpr);
|
||||
m_cfuncp->user1(true); // Mark caller as not a leaf function
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
void visit(AstCCall* nodep) override {
|
||||
m_cfuncp->user1(true); // Mark caller as not a leaf function
|
||||
iterateChildrenConst(nodep);
|
||||
|
|
@ -195,8 +210,11 @@ class LocalizeVisitor final : public VNVisitor {
|
|||
// Remember the reference so we can fix it up later (we always need this as well)
|
||||
m_references(m_cfuncp).emplace(varScopep, nodep);
|
||||
|
||||
// Check if already marked as not optimizable
|
||||
if (!varScopep->user1()) {
|
||||
if (m_inSuperConstructorCallStmt) {
|
||||
// Variable used in super constructor call can't be localized
|
||||
varScopep->user1(true);
|
||||
varScopep->user4(true);
|
||||
} else if (!varScopep->user1()) { // Check if already marked as not optimizable
|
||||
// Note: we only check read variables, as it's ok to localize (and in fact discard)
|
||||
// any variables that are only written but never read.
|
||||
if (nodep->access().isReadOrRW() && !varScopep->user2()) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2025 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Antmicro.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
class Base;
|
||||
int j;
|
||||
function new(int x);
|
||||
j = x;
|
||||
endfunction
|
||||
static function int get_default();
|
||||
return 8;
|
||||
endfunction
|
||||
endclass
|
||||
class Derived extends Base;
|
||||
function new();
|
||||
super.new(get_default());
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
Derived d = new;
|
||||
if (d.j != 8) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue