From 75881754a97108d461a4075833855def3e13905f Mon Sep 17 00:00:00 2001 From: Yutetsu TAKATSUKASA Date: Wed, 4 Nov 2020 06:08:03 +0900 Subject: [PATCH] Fix dangling reference (Issue #2622) (#2623) * collect multiple string literals of "__Vcvt". No functional change is intended. * temporary variable for DPI-C should be static if its type is string * Update src/V3EmitC.cpp Co-authored-by: Wilson Snyder Co-authored-by: Wilson Snyder --- src/V3EmitC.cpp | 11 +++++++++++ src/V3Task.cpp | 27 +++++++++++++++++---------- src/V3Task.h | 1 + 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index b78c82715..6109ff891 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -23,6 +23,7 @@ #include "V3EmitCBase.h" #include "V3Number.h" #include "V3PartitionGraph.h" +#include "V3Task.h" #include "V3TSP.h" #include @@ -1904,6 +1905,16 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) { puts(");\n"); } else { // strings and other fundamental c types + if (nodep->isFuncLocal() && nodep->isString()) { + const string name = nodep->name(); + const string suffix = V3Task::dpiTemporaryVarSuffix(); + // string temporary variable for DPI-C needs to be static because c_str() will be + // passed to C code and the lifetime of the variable must be long enough. See also + // Issue 2622. + const bool beStatic = name.size() >= suffix.size() + && name.substr(name.size() - suffix.size()) == suffix; + if (beStatic) puts("static VL_THREAD_LOCAL "); + } puts(nodep->vlArgType(true, false, false, prefixIfImp)); puts(";\n"); } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index ffe957a22..2f58f79f0 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -683,6 +683,7 @@ private: } void makeDpiExportWrapper(AstNodeFTask* nodep, AstVar* rtnvarp) { + const char* const tmpSuffixp = V3Task::dpiTemporaryVarSuffix(); AstCFunc* dpip = new AstCFunc(nodep->fileline(), nodep->cname(), m_scopep, (rtnvarp ? rtnvarp->dpiArgType(true, true) : "")); dpip->dontCombine(true); @@ -737,7 +738,7 @@ private: argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); args = ""; } - AstVarScope* outvscp = createFuncVar(dpip, portp->name() + "__Vcvt", portp); + AstVarScope* outvscp = createFuncVar(dpip, portp->name() + tmpSuffixp, portp); // No information exposure; is already visible in import/export func template outvscp->varp()->protect(false); portp->protect(false); @@ -764,7 +765,7 @@ private: argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); args = ""; } - AstVarScope* outvscp = createFuncVar(dpip, portp->name() + "__Vcvt", portp); + AstVarScope* outvscp = createFuncVar(dpip, portp->name() + tmpSuffixp, portp); // No information exposure; is already visible in import/export func template outvscp->varp()->protect(false); AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, @@ -789,14 +790,14 @@ private: for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && portp->isWritable() && !portp->isFuncReturn()) { - dpip->addStmtsp(createAssignInternalToDpi(portp, true, "__Vcvt", "")); + dpip->addStmtsp(createAssignInternalToDpi(portp, true, tmpSuffixp, "")); } } } if (rtnvarp) { dpip->addStmtsp(createDpiTemp(rtnvarp, "")); - dpip->addStmtsp(createAssignInternalToDpi(rtnvarp, false, "__Vcvt", "")); + dpip->addStmtsp(createAssignInternalToDpi(rtnvarp, false, tmpSuffixp, "")); string stmt = "return " + rtnvarp->name(); stmt += rtnvarp->basicp()->isDpiPrimitive() ? ";\n" : "[0];\n"; dpip->addStmtsp(new AstCStmt(nodep->fileline(), stmt)); @@ -873,6 +874,7 @@ private: } void bodyDpiImportFunc(AstNodeFTask* nodep, AstVarScope* rtnvscp, AstCFunc* cfuncp) { + const char* const tmpSuffixp = V3Task::dpiTemporaryVarSuffix(); // Convert input/inout arguments to DPI types string args; for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp = stmtp->nextp()) { @@ -914,12 +916,12 @@ private: args += "&"; } - args += portp->name() + "__Vcvt"; + args += portp->name() + tmpSuffixp; - cfuncp->addStmtsp(createDpiTemp(portp, "__Vcvt")); + cfuncp->addStmtsp(createDpiTemp(portp, tmpSuffixp)); if (portp->isNonOutput()) { cfuncp->addStmtsp( - createAssignInternalToDpi(portp, false, "", "__Vcvt")); + createAssignInternalToDpi(portp, false, "", tmpSuffixp)); } } } @@ -935,8 +937,8 @@ private: { // Call the user function string stmt; if (rtnvscp) { // isFunction will no longer work as we unlinked the return var - cfuncp->addStmtsp(createDpiTemp(rtnvscp->varp(), "__Vcvt")); - stmt = rtnvscp->varp()->name() + "__Vcvt"; + cfuncp->addStmtsp(createDpiTemp(rtnvscp->varp(), tmpSuffixp)); + stmt = rtnvscp->varp()->name() + tmpSuffixp; stmt += rtnvscp->varp()->basicp()->isDpiPrimitive() ? " = " : "[0] = "; } stmt += nodep->cname() + "(" + args + ");\n"; @@ -952,7 +954,7 @@ private: AstVarScope* portvscp = VN_CAST( portp->user2p(), VarScope); // Remembered when we created it earlier cfuncp->addStmtsp( - createAssignDpiToInternal(portvscp, portp->name() + "__Vcvt")); + createAssignDpiToInternal(portvscp, portp->name() + tmpSuffixp)); } } } @@ -1577,6 +1579,11 @@ bool V3Task::dpiToInternalFrStmt(AstVar* portp, const string& frName, string& fr return false; } +const char* V3Task::dpiTemporaryVarSuffix() { + static const char suffix[] = "__Vcvt"; + return suffix; +} + void V3Task::taskAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { diff --git a/src/V3Task.h b/src/V3Task.h index 90eed1bab..a1722a16c 100644 --- a/src/V3Task.h +++ b/src/V3Task.h @@ -40,6 +40,7 @@ public: static string assignInternalToDpi(AstVar* portp, bool isPtr, const string& frSuffix, const string& toSuffix, const string& frPrefix = ""); static bool dpiToInternalFrStmt(AstVar* portp, const string& frName, string& frstmt); + static const char* dpiTemporaryVarSuffix(); }; #endif // Guard