Internals: Move AstNodeCCall::m_selfPointer to AstCCall

Other sub-classes of AstNodeCCall do not need the self pointer. Moving
it into the specific sub-class that needs it clarifies V3Descope and
Emit. No functional change intended.
This commit is contained in:
Geza Lore 2021-07-13 17:42:17 +01:00
parent 4081a1a539
commit ddef61d62e
6 changed files with 59 additions and 32 deletions

View File

@ -2612,7 +2612,6 @@ class AstNodeCCall VL_NOT_FINAL : public AstNodeStmt {
// A call of a C++ function, perhaps a AstCFunc or perhaps globally named
// Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal.
AstCFunc* m_funcp;
string m_selfPointer; // Output code object pointer (e.g.: 'this')
string m_argTypes;
protected:
@ -2638,9 +2637,6 @@ public:
virtual bool isPure() const override;
virtual bool isOutputter() const override { return !isPure(); }
AstCFunc* funcp() const { return m_funcp; }
string selfPointer() const { return m_selfPointer; }
void selfPointer(const string& value) { m_selfPointer = value; }
string selfPointerProtect(bool useSelfForThis) const;
void argTypes(const string& str) { m_argTypes = str; }
string argTypes() const { return m_argTypes; }
// op1p reserved for AstCMethodCall

View File

@ -121,7 +121,8 @@ const char* AstNodeCCall::broken() const {
return nullptr;
}
bool AstNodeCCall::isPure() const { return funcp()->pure(); }
string AstNodeCCall::selfPointerProtect(bool useSelfForThis) const {
string AstCCall::selfPointerProtect(bool useSelfForThis) const {
const string& sp
= useSelfForThis ? VString::replaceWord(selfPointer(), "this", "vlSelf") : selfPointer();
return VIdProtect::protectWordsIf(sp, protect());

View File

@ -8880,10 +8880,17 @@ class AstCCall final : public AstNodeCCall {
// C++ function call
// Parents: Anything above a statement
// Children: Args to the function
string m_selfPointer; // Output code object pointer (e.g.: 'this')
public:
AstCCall(FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr)
: ASTGEN_SUPER_CCall(fl, funcp, argsp) {}
ASTNODE_NODE_FUNCS(CCall)
string selfPointer() const { return m_selfPointer; }
void selfPointer(const string& value) { m_selfPointer = value; }
string selfPointerProtect(bool useSelfForThis) const;
};
class AstCMethodCall final : public AstNodeCCall {

View File

@ -73,6 +73,7 @@ private:
// module.
string descopedSelfPointer(const AstScope* scopep) {
UASSERT(scopep, "Var/Func not scoped");
UASSERT(!VN_IS(scopep->modp(), Class), "References to classes handled elsewhere");
// Static functions can't use relative references via 'this->'
const bool relativeRefOk = !m_funcp->isStatic();
@ -83,9 +84,7 @@ private:
if (relativeRefOk && scopep == m_scopep) {
return "this";
} else if (VN_IS(scopep->modp(), Class)) {
return "this";
} else if (!m_modSingleton && relativeRefOk && scopep->aboveScopep() == m_scopep
} else if (relativeRefOk && !m_modSingleton && scopep->aboveScopep() == m_scopep
&& VN_IS(scopep->modp(), Module)) {
// Reference to scope of instance directly under this module, can just "this->cell",
// which can potentially be V3Combined, but note this requires one extra pointer
@ -215,20 +214,37 @@ private:
UASSERT_OBJ(m_scopep, nodep, "Node not under scope");
const AstVar* const varp = nodep->varScopep()->varp();
const AstScope* const scopep = nodep->varScopep()->scopep();
if (!varp->isFuncLocal()) { nodep->selfPointer(descopedSelfPointer(scopep)); }
if (varp->isFuncLocal()) {
// Reference to function locals need no self pointer
nodep->selfPointer("");
} else if (VN_IS(scopep->modp(), Class)) {
// Direct reference to class members are from within the class itself, references from
// outside the class must go via AstMemberSel
nodep->selfPointer("this");
} else {
nodep->selfPointer(descopedSelfPointer(scopep));
}
nodep->varScopep(nullptr);
UINFO(9, " refout " << nodep << endl);
}
virtual void visit(AstNodeCCall* nodep) override {
virtual void visit(AstCCall* nodep) override {
// UINFO(9, " " << nodep << endl);
iterateChildren(nodep);
// Convert the hierch name
UASSERT_OBJ(m_scopep, nodep, "Node not under scope");
const AstScope* const scopep = nodep->funcp()->scopep();
nodep->selfPointer(descopedSelfPointer(scopep));
if (VN_IS(scopep->modp(), Class)) {
// Direct call to class methods are from within the class itself, method calls from
// outside the class must go via AstCMethodCall
nodep->selfPointer("this");
} else {
nodep->selfPointer(descopedSelfPointer(scopep));
}
// Can't do this, as we may have more calls later
// nodep->funcp()->scopep(nullptr);
}
virtual void visit(AstCMethodCall* nodep) override { iterateChildren(nodep); }
virtual void visit(AstCNew* nodep) override { iterateChildren(nodep); }
virtual void visit(AstCFunc* nodep) override {
VL_RESTORER(m_funcp);
if (!nodep->user1()) {

View File

@ -433,12 +433,12 @@ void EmitCFunc::displayNode(AstNode* nodep, AstScopeName* scopenamep, const stri
displayEmit(nodep, isScan);
}
void EmitCFunc::emitCCallArgs(AstNodeCCall* nodep) {
void EmitCFunc::emitCCallArgs(const AstNodeCCall* nodep, const string& selfPointer) {
puts("(");
bool comma = false;
if (nodep->funcp()->isLoose() && !nodep->funcp()->isStatic()) {
UASSERT_OBJ(!nodep->selfPointer().empty(), nodep,
"Call to loose method without self pointer");
puts(nodep->selfPointerProtect(m_useSelfForThis));
UASSERT_OBJ(!selfPointer.empty(), nodep, "Call to loose method without self pointer");
puts(selfPointer);
comma = true;
}
if (!nodep->argTypes().empty()) {
@ -451,6 +451,12 @@ void EmitCFunc::emitCCallArgs(AstNodeCCall* nodep) {
iterate(subnodep);
comma = true;
}
if (VN_IS(nodep->backp(), NodeMath) || VN_IS(nodep->backp(), CReturn)) {
// We should have a separate CCall for math and statement usage, but...
puts(")");
} else {
puts(");\n");
}
}
void EmitCFunc::emitDereference(const string& pointer) {

View File

@ -172,7 +172,7 @@ public:
}
void emitOpName(AstNode* nodep, const string& format, AstNode* lhsp, AstNode* rhsp,
AstNode* thsp);
void emitCCallArgs(AstNodeCCall* nodep);
void emitCCallArgs(const AstNodeCCall* nodep, const string& selfPointer);
void emitDereference(const string& pointer);
void emitCvtPackStr(AstNode* nodep);
void emitCvtWideArray(AstNode* nodep, AstNode* fromp);
@ -353,7 +353,7 @@ public:
}
puts(")");
}
virtual void visit(AstNodeCCall* nodep) override {
virtual void visit(AstCCall* nodep) override {
const AstCFunc* const funcp = nodep->funcp();
if (AstCMethodCall* ccallp = VN_CAST(nodep, CMethodCall)) {
UASSERT_OBJ(!funcp->isLoose(), nodep, "Loose method called via AstCMethodCall");
@ -382,14 +382,22 @@ public:
}
puts(funcp->nameProtect());
}
puts("(");
emitCCallArgs(nodep);
if (VN_IS(nodep->backp(), NodeMath) || VN_IS(nodep->backp(), CReturn)) {
// We should have a separate CCall for math and statement usage, but...
puts(")");
} else {
puts(");\n");
}
emitCCallArgs(nodep, nodep->selfPointerProtect(m_useSelfForThis));
}
virtual void visit(AstCMethodCall* nodep) override {
const AstCFunc* const funcp = nodep->funcp();
UASSERT_OBJ(!funcp->isLoose(), nodep, "Loose method called via AstCMethodCall");
iterate(nodep->fromp());
putbs("->");
puts(funcp->nameProtect());
emitCCallArgs(nodep, "");
}
virtual void visit(AstCNew* nodep) override {
puts("std::make_shared<" + prefixNameProtect(nodep->dtypep()) + ">(");
puts("vlSymsp"); // TODO make this part of argsp, and eliminate when unnecessary
if (nodep->argsp()) puts(", ");
iterateAndNextNull(nodep->argsp());
puts(")");
}
virtual void visit(AstCMethodHard* nodep) override {
iterate(nodep->fromp());
@ -1013,13 +1021,6 @@ public:
puts(cvtToStr(nodep->fileline()->lineno()));
puts(")");
}
virtual void visit(AstCNew* nodep) override {
puts("std::make_shared<" + prefixNameProtect(nodep->dtypep()) + ">(");
puts("vlSymsp"); // TODO make this part of argsp, and eliminate when unnecessary
if (nodep->argsp()) puts(", ");
iterateAndNextNull(nodep->argsp());
puts(")");
}
virtual void visit(AstNewCopy* nodep) override {
puts("std::make_shared<" + prefixNameProtect(nodep->dtypep()) + ">(");
puts("*"); // i.e. make into a reference