Internals: Use magic string for warnMore so lock-free.

This commit is contained in:
Wilson Snyder 2025-05-10 18:06:33 -04:00
parent 680236b03e
commit fe4ad7de64
5 changed files with 32 additions and 15 deletions

View File

@ -113,7 +113,9 @@ void V3ErrorGuarded::vlAbortOrExit() VL_REQUIRES(m_mutex) {
}
}
string V3ErrorGuarded::warnMore() VL_REQUIRES(m_mutex) { return string(msgPrefix().size(), ' '); }
string V3ErrorGuarded::warnMoreSpaces() VL_REQUIRES(m_mutex) {
return string(msgPrefix().size(), ' ');
}
void V3ErrorGuarded::suppressThisWarning() VL_REQUIRES(m_mutex) {
#ifndef V3ERROR_NO_GLOBAL_
@ -155,6 +157,8 @@ void V3ErrorGuarded::v3errorEnd(std::ostringstream& sstr, const string& extra)
// Suppress duplicate messages
if (!m_messages.insert(firstLine).second) return;
msg = VString::replaceSubstr(msg, V3Error::warnMore(), warnMoreSpaces());
string msg_additional;
{
string::size_type pos;
@ -172,7 +176,8 @@ void V3ErrorGuarded::v3errorEnd(std::ostringstream& sstr, const string& extra)
msg_additional.erase(pos + 1, 1);
}
if (!extra.empty() && !m_errorSuppressed) {
const string extraMsg = warnMore() + extra + "\n";
string extraMsg = VString::replaceSubstr(extra, V3Error::warnMore(), warnMoreSpaces());
extraMsg = warnMoreSpaces() + extraMsg + "\n";
const size_t pos = msg.find('\n');
msg.insert(pos + 1, extraMsg);
}
@ -193,7 +198,7 @@ void V3ErrorGuarded::v3errorEnd(std::ostringstream& sstr, const string& extra)
&& !m_describedEachWarn[m_errorCode]) {
m_describedEachWarn[m_errorCode] = true;
if (m_errorCode >= V3ErrorCode::EC_FIRST_NAMED) {
std::cerr << warnMore() << "... For " << (anError ? "error" : "warning")
std::cerr << warnMoreSpaces() << "... For " << (anError ? "error" : "warning")
<< " description see " << m_errorCode.url() << endl;
} else if (m_errCount >= 1
&& (m_errorCode == V3ErrorCode::EC_FATAL
@ -201,24 +206,24 @@ void V3ErrorGuarded::v3errorEnd(std::ostringstream& sstr, const string& extra)
|| m_errorCode == V3ErrorCode::EC_FATALSRC)
&& !m_tellInternal) {
m_tellInternal = true;
std::cerr << warnMore()
std::cerr << warnMoreSpaces()
<< "... This fatal error may be caused by the earlier error(s);"
" resolve those first."
<< endl;
} else if (!m_tellManual) {
m_tellManual = true;
std::cerr << warnMore() << "... See the manual at " << m_errorCode.url()
std::cerr << warnMoreSpaces() << "... See the manual at " << m_errorCode.url()
<< " for more assistance." << endl;
}
if (!m_pretendError[m_errorCode] && !m_errorCode.hardError()) {
std::cerr << warnMore() << "... Use \"/* verilator lint_off "
std::cerr << warnMoreSpaces() << "... Use \"/* verilator lint_off "
<< m_errorCode.ascii()
<< " */\" and lint_on around source to disable this message." << endl;
if (m_errorCode.dangerous()) {
std::cerr << warnMore() << "*** See " << m_errorCode.url()
std::cerr << warnMoreSpaces() << "*** See " << m_errorCode.url()
<< " before disabling this,\n";
std::cerr << warnMore() << "else you may end up with different sim results."
<< endl;
std::cerr << warnMoreSpaces()
<< "else you may end up with different sim results." << endl;
}
}
}

View File

@ -349,7 +349,7 @@ public:
V3RecursiveMutex m_mutex; // Make sure only single thread is in class
string msgPrefix() VL_REQUIRES(m_mutex); // returns %Error/%Warn
string warnMore() VL_REQUIRES(m_mutex);
string warnMoreSpaces() VL_REQUIRES(m_mutex);
void execErrorExitCb() VL_REQUIRES(m_mutex) {
if (m_errorExitCb) m_errorExitCb();
}
@ -503,7 +503,7 @@ public:
}
// When printing an error/warning, print prefix for multiline message
static string warnMore() VL_REQUIRES(s().m_mutex) { return s().warnMore(); }
static string warnMore() VL_MT_SAFE { return "__WARNMORE__"; }
// This function marks place in error message from which point message
// should be printed after information on the error code.
// The post-processing is done in v3errorEnd function.

View File

@ -452,16 +452,16 @@ void FileLine::v3errorEnd(std::ostringstream& sstr, const string& extra)
string FileLine::warnMore() const VL_REQUIRES(V3Error::s().m_mutex) {
if (lastLineno()) {
return V3Error::s().warnMore() + string(ascii().size(), ' ') + ": ";
return V3Error::warnMore() + string(ascii().size(), ' ') + ": ";
} else {
return V3Error::s().warnMore();
return V3Error::warnMore();
}
}
string FileLine::warnOther() const VL_REQUIRES(V3Error::s().m_mutex) {
if (lastLineno()) {
return V3Error::s().warnMore() + ascii() + ": ";
return V3Error::warnMore() + ascii() + ": ";
} else {
return V3Error::s().warnMore();
return V3Error::warnMore();
}
};

View File

@ -271,6 +271,16 @@ double VString::parseDouble(const string& str, bool* successp) {
return d;
}
string VString::replaceSubstr(const string& str, const string& from, const string& to) {
string result = str;
const size_t len = from.size();
UASSERT_STATIC(len > 0, "Cannot replace empty string");
for (size_t pos = 0; (pos = result.find(from, pos)) != string::npos; pos += len) {
result.replace(pos, len, to);
}
return result;
}
string VString::replaceWord(const string& str, const string& from, const string& to) {
string result = str;
const size_t len = from.size();

View File

@ -126,6 +126,8 @@ public:
static string::size_type leadingWhitespaceCount(const string& str);
// Return double by parsing string
static double parseDouble(const string& str, bool* successp);
// Replace substring. Often replaceWord is more appropriate.
static string replaceSubstr(const string& str, const string& from, const string& to);
// Replace all occurrences of the word 'from' in 'str' with 'to'. A word is considered
// to be a consecutive sequence of the characters [a-zA-Z0-9_]. Sub-words are not replaced.
// e.g.: replaceWords("one apple bad_apple", "apple", "banana") -> "one banana bad_apple"