Support super.new calls (#3789)
This commit is contained in:
parent
468a33b61c
commit
073dc03adc
|
|
@ -550,7 +550,7 @@ private:
|
||||||
string m_cname; // C name, for dpiExports
|
string m_cname; // C name, for dpiExports
|
||||||
string m_rtnType; // void, bool, or other return type
|
string m_rtnType; // void, bool, or other return type
|
||||||
string m_argTypes; // Argument types
|
string m_argTypes; // Argument types
|
||||||
string m_ctorInits; // Constructor sub-class inits
|
string m_baseCtors; // Base class constructor
|
||||||
string m_ifdef; // #ifdef symbol around this function
|
string m_ifdef; // #ifdef symbol around this function
|
||||||
VBoolOrUnknown m_isConst; // Function is declared const (*this not changed)
|
VBoolOrUnknown m_isConst; // Function is declared const (*this not changed)
|
||||||
bool m_isStatic : 1; // Function is static (no need for a 'this' pointer)
|
bool m_isStatic : 1; // Function is static (no need for a 'this' pointer)
|
||||||
|
|
@ -611,7 +611,7 @@ public:
|
||||||
bool same(const AstNode* samep) const override {
|
bool same(const AstNode* samep) const override {
|
||||||
const AstCFunc* const asamep = static_cast<const AstCFunc*>(samep);
|
const AstCFunc* const asamep = static_cast<const AstCFunc*>(samep);
|
||||||
return ((isTrace() == asamep->isTrace()) && (rtnTypeVoid() == asamep->rtnTypeVoid())
|
return ((isTrace() == asamep->isTrace()) && (rtnTypeVoid() == asamep->rtnTypeVoid())
|
||||||
&& (argTypes() == asamep->argTypes()) && (ctorInits() == asamep->ctorInits())
|
&& (argTypes() == asamep->argTypes()) && (baseCtors() == asamep->baseCtors())
|
||||||
&& isLoose() == asamep->isLoose()
|
&& isLoose() == asamep->isLoose()
|
||||||
&& (!(dpiImportPrototype() || dpiExportImpl()) || name() == asamep->name()));
|
&& (!(dpiImportPrototype() || dpiExportImpl()) || name() == asamep->name()));
|
||||||
}
|
}
|
||||||
|
|
@ -644,8 +644,8 @@ public:
|
||||||
void funcPublic(bool flag) { m_funcPublic = flag; }
|
void funcPublic(bool flag) { m_funcPublic = flag; }
|
||||||
void argTypes(const string& str) { m_argTypes = str; }
|
void argTypes(const string& str) { m_argTypes = str; }
|
||||||
string argTypes() const { return m_argTypes; }
|
string argTypes() const { return m_argTypes; }
|
||||||
void ctorInits(const string& str) { m_ctorInits = str; }
|
void baseCtors(const string& str) { m_baseCtors = str; }
|
||||||
string ctorInits() const { return m_ctorInits; }
|
string baseCtors() const { return m_baseCtors; }
|
||||||
void ifdef(const string& str) { m_ifdef = str; }
|
void ifdef(const string& str) { m_ifdef = str; }
|
||||||
string ifdef() const { return m_ifdef; }
|
string ifdef() const { return m_ifdef; }
|
||||||
bool isConstructor() const { return m_isConstructor; }
|
bool isConstructor() const { return m_isConstructor; }
|
||||||
|
|
|
||||||
|
|
@ -422,11 +422,7 @@ void EmitCFunc::emitCCallArgs(const AstNodeCCall* nodep, const string& selfPoint
|
||||||
puts(nodep->argTypes());
|
puts(nodep->argTypes());
|
||||||
comma = true;
|
comma = true;
|
||||||
}
|
}
|
||||||
for (AstNode* subnodep = nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
|
putCommaIterateNext(nodep->argsp(), comma);
|
||||||
if (comma) puts(", ");
|
|
||||||
iterate(subnodep);
|
|
||||||
comma = true;
|
|
||||||
}
|
|
||||||
puts(")");
|
puts(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,13 @@ public:
|
||||||
m_emitConstInit = true;
|
m_emitConstInit = true;
|
||||||
iterate(initp);
|
iterate(initp);
|
||||||
}
|
}
|
||||||
|
void putCommaIterateNext(AstNode* nodep, bool comma = false) {
|
||||||
|
for (AstNode* subnodep = nodep; subnodep; subnodep = subnodep->nextp()) {
|
||||||
|
if (comma) puts(", ");
|
||||||
|
iterate(subnodep);
|
||||||
|
comma = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
using EmitCConstInit::visit;
|
using EmitCConstInit::visit;
|
||||||
|
|
@ -221,11 +228,24 @@ public:
|
||||||
if (nodep->isInline()) puts("VL_INLINE_OPT ");
|
if (nodep->isInline()) puts("VL_INLINE_OPT ");
|
||||||
emitCFuncHeader(nodep, m_modp, /* withScope: */ true);
|
emitCFuncHeader(nodep, m_modp, /* withScope: */ true);
|
||||||
|
|
||||||
// TODO perhaps better to have a new AstCCtorInit so we can pass arguments
|
if (!nodep->baseCtors().empty()) {
|
||||||
// rather than requiring a string here
|
|
||||||
if (!nodep->ctorInits().empty()) {
|
|
||||||
puts(": ");
|
puts(": ");
|
||||||
puts(nodep->ctorInits());
|
puts(nodep->baseCtors());
|
||||||
|
puts("(vlSymsp");
|
||||||
|
// 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)) {
|
||||||
|
putCommaIterateNext(newRefp->argsp(), true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
puts(")");
|
||||||
}
|
}
|
||||||
puts(" {\n");
|
puts(" {\n");
|
||||||
|
|
||||||
|
|
@ -417,15 +437,13 @@ public:
|
||||||
iterate(nodep->exprp());
|
iterate(nodep->exprp());
|
||||||
}
|
}
|
||||||
void visit(AstCNew* nodep) override {
|
void visit(AstCNew* nodep) override {
|
||||||
bool comma = false;
|
if (VN_IS(nodep->dtypep(), VoidDType)) {
|
||||||
puts("VL_NEW(" + prefixNameProtect(nodep->dtypep()) + ", ");
|
// super.new case
|
||||||
puts("vlSymsp"); // TODO make this part of argsp, and eliminate when unnecessary
|
return;
|
||||||
if (nodep->argsp()) comma = true;
|
|
||||||
for (AstNode* subnodep = nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
|
|
||||||
if (comma) puts(", ");
|
|
||||||
iterate(subnodep);
|
|
||||||
comma = true;
|
|
||||||
}
|
}
|
||||||
|
// assignment case
|
||||||
|
puts("VL_NEW(" + prefixNameProtect(nodep->dtypep()) + ", vlSymsp");
|
||||||
|
putCommaIterateNext(nodep->argsp(), true);
|
||||||
puts(")");
|
puts(")");
|
||||||
}
|
}
|
||||||
void visit(AstCMethodHard* nodep) override {
|
void visit(AstCMethodHard* nodep) override {
|
||||||
|
|
|
||||||
|
|
@ -1181,8 +1181,8 @@ private:
|
||||||
cfuncp->isConstructor(true);
|
cfuncp->isConstructor(true);
|
||||||
AstClass* const classp = m_statep->getClassp(nodep);
|
AstClass* const classp = m_statep->getClassp(nodep);
|
||||||
if (classp->extendsp()) {
|
if (classp->extendsp()) {
|
||||||
cfuncp->ctorInits(EmitCBaseVisitor::prefixNameProtect(classp->extendsp()->classp())
|
cfuncp->baseCtors(
|
||||||
+ "(vlSymsp)");
|
EmitCBaseVisitor::prefixNameProtect(classp->extendsp()->classp()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cfuncp->dpiExportImpl()) cfuncp->cname(nodep->cname());
|
if (cfuncp->dpiExportImpl()) cfuncp->cname(nodep->cname());
|
||||||
|
|
|
||||||
|
|
@ -3555,22 +3555,32 @@ private:
|
||||||
|
|
||||||
void visit(AstNew* nodep) override {
|
void visit(AstNew* nodep) override {
|
||||||
if (nodep->didWidth()) return;
|
if (nodep->didWidth()) return;
|
||||||
AstClassRefDType* const refp
|
AstClass* classp = nullptr;
|
||||||
= m_vup ? VN_CAST(m_vup->dtypeNullSkipRefp(), ClassRefDType) : nullptr;
|
if (VN_IS(nodep->backp(), Assign)) { // assignment case
|
||||||
if (!refp) { // e.g. int a = new;
|
AstClassRefDType* const refp
|
||||||
nodep->v3error("new() not expected in this context");
|
= m_vup ? VN_CAST(m_vup->dtypeNullSkipRefp(), ClassRefDType) : nullptr;
|
||||||
return;
|
if (!refp) { // e.g. int a = new;
|
||||||
}
|
nodep->v3error("new() not expected in this context");
|
||||||
nodep->dtypep(refp);
|
return;
|
||||||
|
}
|
||||||
|
nodep->dtypep(refp);
|
||||||
|
|
||||||
AstClass* const classp = refp->classp();
|
classp = refp->classp();
|
||||||
UASSERT_OBJ(classp, nodep, "Unlinked");
|
UASSERT_OBJ(classp, nodep, "Unlinked");
|
||||||
if (AstNodeFTask* const ftaskp = VN_CAST(classp->findMember("new"), Func)) {
|
if (AstNodeFTask* const ftaskp = VN_CAST(classp->findMember("new"), Func)) {
|
||||||
nodep->taskp(ftaskp);
|
nodep->taskp(ftaskp);
|
||||||
nodep->classOrPackagep(classp);
|
nodep->classOrPackagep(classp);
|
||||||
} else {
|
} else {
|
||||||
// Either made explicitly or V3LinkDot made implicitly
|
// Either made explicitly or V3LinkDot made implicitly
|
||||||
classp->v3fatalSrc("Can't find class's new");
|
classp->v3fatalSrc("Can't find class's new");
|
||||||
|
}
|
||||||
|
} else { // super.new case
|
||||||
|
// in this case class and taskp() should be properly linked in V3LinkDot.cpp during
|
||||||
|
// "super" reference resolution
|
||||||
|
classp = VN_CAST(nodep->classOrPackagep(), Class);
|
||||||
|
UASSERT_OBJ(classp, nodep, "Unlinked classOrPackagep()");
|
||||||
|
UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked taskp()");
|
||||||
|
nodep->dtypeFrom(nodep->taskp());
|
||||||
}
|
}
|
||||||
if (classp->isVirtual()) {
|
if (classp->isVirtual()) {
|
||||||
nodep->v3error(
|
nodep->v3error(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2022 by Antmicro Ltd. 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
|
||||||
|
|
||||||
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
|
compile();
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2022 by Antmicro Ltd.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
`define stop $stop
|
||||||
|
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||||
|
|
||||||
|
class Foo;
|
||||||
|
int x;
|
||||||
|
function new;
|
||||||
|
this.x = 10;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class Bar extends Foo;
|
||||||
|
function new;
|
||||||
|
super.new;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class BarUnusedArg extends Foo;
|
||||||
|
function new (int a);
|
||||||
|
super.new;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class FooArg;
|
||||||
|
int x;
|
||||||
|
function new (int a);
|
||||||
|
this.x = a;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class BarArg extends FooArg;
|
||||||
|
function new (int a);
|
||||||
|
super.new(a);
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class BarExpr extends FooArg;
|
||||||
|
function new (int a, string b);
|
||||||
|
super.new(a + b.len());
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class Foo2Args;
|
||||||
|
int x;
|
||||||
|
function new (int a, int b);
|
||||||
|
this.x = a + b;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class Bar2Args extends Foo2Args;
|
||||||
|
function new (int a, int b);
|
||||||
|
super.new(a, b);
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
);
|
||||||
|
|
||||||
|
class FooInModule;
|
||||||
|
int x;
|
||||||
|
function new;
|
||||||
|
this.x = 15;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class BarInModule extends FooInModule;
|
||||||
|
function new;
|
||||||
|
super.new;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
Bar bar;
|
||||||
|
BarInModule barInModule;
|
||||||
|
BarUnusedArg barUnusedArg;
|
||||||
|
BarArg barArg;
|
||||||
|
BarExpr barExpr;
|
||||||
|
Bar2Args bar2Args;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
bar = new;
|
||||||
|
`checkh(bar.x, 10);
|
||||||
|
barInModule = new;
|
||||||
|
`checkh(barInModule.x, 15);
|
||||||
|
barUnusedArg = new(2);
|
||||||
|
`checkh(barUnusedArg.x, 10);
|
||||||
|
barArg = new(2);
|
||||||
|
`checkh(barArg.x, 2);
|
||||||
|
barExpr = new (7, "ABCDEFGHI");
|
||||||
|
`checkh(barExpr.x, 16);
|
||||||
|
bar2Args = new(2, 12);
|
||||||
|
`checkh(bar2Args.x, 14);
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue