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 <wsnyder@wsnyder.org>

Co-authored-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
Yutetsu TAKATSUKASA 2020-11-04 06:08:03 +09:00 committed by GitHub
parent 0505816d31
commit 75881754a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 10 deletions

View File

@ -23,6 +23,7 @@
#include "V3EmitCBase.h"
#include "V3Number.h"
#include "V3PartitionGraph.h"
#include "V3Task.h"
#include "V3TSP.h"
#include <algorithm>
@ -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");
}

View File

@ -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);
{

View File

@ -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