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)
|
// AstVarScope::user3p() -> Set of CFuncs referencing this VarScope. (via m_accessors)
|
||||||
// AstCFunc::user4p() -> Multimap of 'VarScope -> VarRefs that reference that VarScope'
|
// AstCFunc::user4p() -> Multimap of 'VarScope -> VarRefs that reference that VarScope'
|
||||||
// in this function. (via m_references)
|
// 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 VNUser1InUse m_user1InUse;
|
||||||
const VNUser3InUse m_user3InUse;
|
const VNUser3InUse m_user3InUse;
|
||||||
const VNUser4InUse m_user4InUse;
|
const VNUser4InUse m_user4InUse;
|
||||||
|
|
@ -60,11 +63,15 @@ class LocalizeVisitor final : public VNVisitor {
|
||||||
// STATE - for current visit position (use VL_RESTORER)
|
// STATE - for current visit position (use VL_RESTORER)
|
||||||
AstCFunc* m_cfuncp = nullptr; // Current active function
|
AstCFunc* m_cfuncp = nullptr; // Current active function
|
||||||
uint32_t m_nodeDepth = 0; // Node depth under m_cfuncp
|
uint32_t m_nodeDepth = 0; // Node depth under m_cfuncp
|
||||||
|
bool m_inSuperConstructorCallStmt = false; // If under super constructor call statement
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
bool isOptimizable(AstVarScope* nodep) {
|
bool isOptimizable(AstVarScope* nodep) {
|
||||||
// Don't want to malloc/free the backing store all the time
|
// Don't want to malloc/free the backing store all the time
|
||||||
if (VN_IS(nodep->dtypep(), NBACommitQueueDType)) return false;
|
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 ...
|
return ((!nodep->user1() // Not marked as not optimizable, or ...
|
||||||
// .. a block temp used in a single CFunc
|
// .. a block temp used in a single CFunc
|
||||||
|| (nodep->varp()->varType() == VVarType::BLOCKTEMP
|
|| (nodep->varp()->varType() == VVarType::BLOCKTEMP
|
||||||
|
|
@ -147,6 +154,14 @@ class LocalizeVisitor final : public VNVisitor {
|
||||||
iterateChildrenConst(nodep);
|
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 {
|
void visit(AstCCall* nodep) override {
|
||||||
m_cfuncp->user1(true); // Mark caller as not a leaf function
|
m_cfuncp->user1(true); // Mark caller as not a leaf function
|
||||||
iterateChildrenConst(nodep);
|
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)
|
// Remember the reference so we can fix it up later (we always need this as well)
|
||||||
m_references(m_cfuncp).emplace(varScopep, nodep);
|
m_references(m_cfuncp).emplace(varScopep, nodep);
|
||||||
|
|
||||||
// Check if already marked as not optimizable
|
if (m_inSuperConstructorCallStmt) {
|
||||||
if (!varScopep->user1()) {
|
// 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)
|
// 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.
|
// any variables that are only written but never read.
|
||||||
if (nodep->access().isReadOrRW() && !varScopep->user2()) {
|
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