mirror of
https://github.com/verilator/verilator.git
synced 2025-01-05 22:27:35 +00:00
Merge branch 'master' into develop-v5
This commit is contained in:
commit
d8b5359fcb
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
\#*
|
||||
.#*
|
||||
.gdb_history
|
||||
.nfs*
|
||||
*~
|
||||
*.tidy
|
||||
|
@ -48,6 +48,7 @@ exclude_line_regexp(r'\bNUM_ASSERT')
|
||||
exclude_line_regexp(r'\bERROR_RSVD_WORD')
|
||||
exclude_line_regexp(r'\bV3ERROR_NA')
|
||||
exclude_line_regexp(r'\bUINFO\b')
|
||||
exclude_line_regexp(r'\bVL_DEFINE_DEBUG_FUNCTIONS\b')
|
||||
|
||||
# Exclude for branch coverage only
|
||||
exclude_branch_regexp(r'\bdebug\(\)')
|
||||
|
14
src/V3Ast.h
14
src/V3Ast.h
@ -1497,13 +1497,15 @@ class AstNode VL_NOT_FINAL {
|
||||
AstNodeDType* m_dtypep = nullptr; // Data type of output or assignment (etc)
|
||||
AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list
|
||||
FileLine* m_fileline; // Where it was declared
|
||||
#ifdef VL_DEBUG
|
||||
// Only keep track of the edit count in the node in the debug build.
|
||||
// In the release build we will take the space saving instead.
|
||||
uint64_t m_editCount; // When it was last edited
|
||||
#endif
|
||||
static uint64_t s_editCntGbl; // Global edit counter
|
||||
// Global edit counter, last value for printing * near node #s
|
||||
static uint64_t s_editCntLast;
|
||||
static uint64_t s_editCntLast; // Last committed value of global edit counter
|
||||
|
||||
AstNode* m_clonep
|
||||
= nullptr; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY)
|
||||
AstNode* m_clonep = nullptr; // Pointer to clone/source of node (only for *LAST* cloneTree())
|
||||
static int s_cloneCntGbl; // Count of which userp is set
|
||||
|
||||
// This member ordering both allows 64 bit alignment and puts associated data together
|
||||
@ -1774,10 +1776,14 @@ public:
|
||||
static void user5ClearTree() { VNUser5InUse::clear(); } // Clear userp()'s across the entire tree
|
||||
// clang-format on
|
||||
|
||||
#ifdef VL_DEBUG
|
||||
uint64_t editCount() const { return m_editCount; }
|
||||
void editCountInc() {
|
||||
m_editCount = ++s_editCntGbl; // Preincrement, so can "watch AstNode::s_editCntGbl=##"
|
||||
}
|
||||
#else
|
||||
void editCountInc() { ++s_editCntGbl; }
|
||||
#endif
|
||||
static uint64_t editCountLast() { return s_editCntLast; }
|
||||
static uint64_t editCountGbl() { return s_editCntGbl; }
|
||||
static void editCountSetLast() { s_editCntLast = editCountGbl(); }
|
||||
|
@ -1313,10 +1313,10 @@ static std::string nodeAddr(const AstNode* nodep) {
|
||||
}
|
||||
|
||||
void AstNode::dump(std::ostream& str) const {
|
||||
str << typeName() << " "
|
||||
<< nodeAddr(this)
|
||||
//<< " " << nodeAddr(m_backp)
|
||||
str << typeName() << " " << nodeAddr(this)
|
||||
#ifdef VL_DEBUG
|
||||
<< " <e" << std::dec << editCount() << ((editCount() >= editCountLast()) ? "#>" : ">")
|
||||
#endif
|
||||
<< " {" << fileline()->filenameLetters() << std::dec << fileline()->lastLineno()
|
||||
<< fileline()->firstColumnLetters() << "}";
|
||||
if (user1p()) str << " u1=" << nodeAddr(user1p());
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include <unordered_set>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
@ -38,7 +39,7 @@ VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
//######################################################################
|
||||
// FileLineSingleton class functions
|
||||
|
||||
string FileLineSingleton::filenameLetters(int fileno) {
|
||||
string FileLineSingleton::filenameLetters(fileNameIdx_t fileno) {
|
||||
constexpr int size
|
||||
= 1 + (64 / 4); // Each letter retires more than 4 bits of a > 64 bit number
|
||||
char out[size];
|
||||
@ -60,14 +61,18 @@ string FileLineSingleton::filenameLetters(int fileno) {
|
||||
|
||||
//! We associate a language with each source file, so we also set the default
|
||||
//! for this.
|
||||
int FileLineSingleton::nameToNumber(const string& filename) {
|
||||
const auto it = vlstd::as_const(m_namemap).find(filename);
|
||||
if (VL_LIKELY(it != m_namemap.end())) return it->second;
|
||||
const int num = m_names.size();
|
||||
m_names.push_back(filename);
|
||||
m_languages.push_back(V3LangCode::mostRecent());
|
||||
m_namemap.emplace(filename, num);
|
||||
return num;
|
||||
FileLineSingleton::fileNameIdx_t FileLineSingleton::nameToNumber(const string& filename) {
|
||||
const auto pair = m_namemap.emplace(filename, 0);
|
||||
fileNameIdx_t& idx = pair.first->second;
|
||||
if (pair.second) {
|
||||
const size_t nextIdx = m_names.size();
|
||||
UASSERT(nextIdx <= std::numeric_limits<fileNameIdx_t>::max(),
|
||||
"Too many input files (" + cvtToStr(nextIdx) + "+).");
|
||||
idx = static_cast<fileNameIdx_t>(nextIdx);
|
||||
m_names.push_back(filename);
|
||||
m_languages.push_back(V3LangCode::mostRecent());
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
//! Support XML output
|
||||
@ -82,8 +87,46 @@ void FileLineSingleton::fileNameNumMapDumpXml(std::ostream& os) {
|
||||
os << "</files>\n";
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// VFileContents class functions
|
||||
FileLineSingleton::msgEnSetIdx_t FileLineSingleton::addMsgEnBitSet(const MsgEnBitSet& bitSet) {
|
||||
const auto pair = m_internedMsgEnIdxs.emplace(bitSet, 0);
|
||||
msgEnSetIdx_t& idx = pair.first->second;
|
||||
if (pair.second) {
|
||||
const size_t nextIdx = m_internedMsgEns.size();
|
||||
UASSERT(nextIdx <= std::numeric_limits<msgEnSetIdx_t>::max(),
|
||||
"Too many unique message enable sets (" + cvtToStr(nextIdx) + "+).");
|
||||
idx = static_cast<msgEnSetIdx_t>(nextIdx);
|
||||
m_internedMsgEns.push_back(bitSet);
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
FileLineSingleton::msgEnSetIdx_t FileLineSingleton::defaultMsgEnIndex() {
|
||||
MsgEnBitSet msgEnBitSet;
|
||||
for (int i = V3ErrorCode::EC_MIN; i < V3ErrorCode::_ENUM_MAX; ++i) {
|
||||
msgEnBitSet.set(i, !V3ErrorCode{i}.defaultsOff());
|
||||
}
|
||||
return addMsgEnBitSet(msgEnBitSet);
|
||||
}
|
||||
|
||||
FileLineSingleton::msgEnSetIdx_t FileLineSingleton::msgEnSetBit(msgEnSetIdx_t setIdx,
|
||||
size_t bitIdx, bool value) {
|
||||
if (msgEn(setIdx).test(bitIdx) == value) return setIdx;
|
||||
MsgEnBitSet msgEnBitSet{msgEn(setIdx)};
|
||||
msgEnBitSet.set(bitIdx, value);
|
||||
return addMsgEnBitSet(msgEnBitSet);
|
||||
}
|
||||
|
||||
FileLineSingleton::msgEnSetIdx_t FileLineSingleton::msgEnAnd(msgEnSetIdx_t lhsIdx,
|
||||
msgEnSetIdx_t rhsIdx) {
|
||||
MsgEnBitSet msgEnBitSet{msgEn(lhsIdx)};
|
||||
msgEnBitSet &= msgEn(rhsIdx);
|
||||
if (msgEnBitSet == msgEn(lhsIdx)) return lhsIdx;
|
||||
if (msgEnBitSet == msgEn(rhsIdx)) return rhsIdx;
|
||||
return addMsgEnBitSet(msgEnBitSet);
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
// VFileContents class functions
|
||||
|
||||
void VFileContent::pushText(const string& text) {
|
||||
if (m_lines.size() == 0) {
|
||||
@ -136,22 +179,17 @@ std::ostream& operator<<(std::ostream& os, VFileContent* contentp) {
|
||||
return os;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// FileLine class functions
|
||||
// ######################################################################
|
||||
// FileLine class functions
|
||||
|
||||
// Sort of a singleton
|
||||
FileLine::FileLine(FileLine::EmptySecret) {
|
||||
m_filenameno = singleton().nameToNumber(FileLine::builtInFilename());
|
||||
|
||||
m_warnOn = 0;
|
||||
for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) {
|
||||
const V3ErrorCode code{codei};
|
||||
warnOff(code, code.defaultsOff());
|
||||
}
|
||||
FileLine::~FileLine() {
|
||||
if (m_contentp) VL_DO_DANGLING(m_contentp->refDec(), m_contentp);
|
||||
}
|
||||
|
||||
void FileLine::newContent() {
|
||||
m_contentp = std::make_shared<VFileContent>();
|
||||
if (m_contentp) VL_DO_DANGLING(m_contentp->refDec(), m_contentp);
|
||||
m_contentp = new VFileContent;
|
||||
m_contentp->refInc();
|
||||
m_contentLineno = 1;
|
||||
}
|
||||
|
||||
@ -318,22 +356,14 @@ void FileLine::warnStyleOff(bool flag) {
|
||||
}
|
||||
|
||||
bool FileLine::warnIsOff(V3ErrorCode code) const {
|
||||
if (!m_warnOn.test(code)) return true;
|
||||
if (!defaultFileLine().m_warnOn.test(code)) return true; // Global overrides local
|
||||
if ((code.lintError() || code.styleError()) && !m_warnOn.test(V3ErrorCode::I_LINT)) {
|
||||
if (!msgEn().test(code)) return true;
|
||||
if (!defaultFileLine().msgEn().test(code)) return true; // Global overrides local
|
||||
if ((code.lintError() || code.styleError()) && !msgEn().test(V3ErrorCode::I_LINT)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FileLine::modifyStateInherit(const FileLine* fromp) {
|
||||
// Any warnings that are off in "from", become off in "this".
|
||||
for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) {
|
||||
const V3ErrorCode code{codei};
|
||||
if (fromp->warnIsOff(code)) warnOff(code, true);
|
||||
}
|
||||
}
|
||||
|
||||
void FileLine::v3errorEnd(std::ostringstream& sstr, const string& extra) {
|
||||
std::ostringstream nsstr;
|
||||
if (lastLineno()) nsstr << this;
|
||||
|
147
src/V3FileLine.h
147
src/V3FileLine.h
@ -23,14 +23,17 @@
|
||||
#include "V3Error.h"
|
||||
#include "V3LangCode.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <bitset>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
//######################################################################
|
||||
// ######################################################################
|
||||
|
||||
class FileLine;
|
||||
|
||||
@ -39,68 +42,109 @@ class FileLine;
|
||||
//! This singleton class contains tables of data that are unchanging in each
|
||||
//! source file (each with its own unique filename number).
|
||||
class FileLineSingleton final {
|
||||
friend class FileLine;
|
||||
|
||||
// TYPES
|
||||
using fileNameIdx_t = uint16_t; // Increase width if 64K input files are not enough
|
||||
using msgEnSetIdx_t = uint16_t; // Increase width if 64K unique message sets are not enough
|
||||
using MsgEnBitSet = std::bitset<V3ErrorCode::_ENUM_MAX>;
|
||||
|
||||
// MEMBERS
|
||||
std::map<const std::string, int> m_namemap; // filenameno for each filename
|
||||
std::map<const std::string, fileNameIdx_t> m_namemap; // filenameno for each filename
|
||||
std::deque<string> m_names; // filename text for each filenameno
|
||||
std::deque<V3LangCode> m_languages; // language for each filenameno
|
||||
|
||||
// Map from flag set to the index in m_internedMsgEns for interning
|
||||
std::unordered_map<MsgEnBitSet, msgEnSetIdx_t> m_internedMsgEnIdxs;
|
||||
// Interned message enablement flag sets
|
||||
std::vector<MsgEnBitSet> m_internedMsgEns;
|
||||
|
||||
// CONSTRUCTORS
|
||||
FileLineSingleton() = default;
|
||||
~FileLineSingleton() = default;
|
||||
|
||||
protected:
|
||||
friend class FileLine;
|
||||
int nameToNumber(const string& filename);
|
||||
string numberToName(int filenameno) const { return m_names[filenameno]; }
|
||||
V3LangCode numberToLang(int filenameno) const { return m_languages[filenameno]; }
|
||||
void numberToLang(int filenameno, const V3LangCode& l) { m_languages[filenameno] = l; }
|
||||
fileNameIdx_t nameToNumber(const string& filename);
|
||||
string numberToName(fileNameIdx_t filenameno) const { return m_names[filenameno]; }
|
||||
V3LangCode numberToLang(fileNameIdx_t filenameno) const { return m_languages[filenameno]; }
|
||||
void numberToLang(fileNameIdx_t filenameno, const V3LangCode& l) {
|
||||
m_languages[filenameno] = l;
|
||||
}
|
||||
void clear() {
|
||||
m_namemap.clear();
|
||||
m_names.clear();
|
||||
m_languages.clear();
|
||||
}
|
||||
void fileNameNumMapDumpXml(std::ostream& os);
|
||||
static string filenameLetters(int fileno);
|
||||
static string filenameLetters(fileNameIdx_t fileno);
|
||||
|
||||
// Add given bitset to the interned bitsets, return interned index
|
||||
msgEnSetIdx_t addMsgEnBitSet(const MsgEnBitSet& bitSet);
|
||||
// Add index of default bitset
|
||||
msgEnSetIdx_t defaultMsgEnIndex();
|
||||
// Set bitIdx to value in bitset at interned idnex setIdx, return interned index of result
|
||||
msgEnSetIdx_t msgEnSetBit(msgEnSetIdx_t setIdx, size_t bitIdx, bool value);
|
||||
// Return index to intersection set
|
||||
msgEnSetIdx_t msgEnAnd(msgEnSetIdx_t lhsIdx, msgEnSetIdx_t rhsIdx);
|
||||
// Retrieve interned bitset at given interned index. The returned reference is not persistent.
|
||||
const MsgEnBitSet& msgEn(msgEnSetIdx_t idx) const { return m_internedMsgEns.at(idx); }
|
||||
};
|
||||
|
||||
//! All source lines from a file/stream, to enable errors to show sources
|
||||
// All source lines from a file/stream, to enable errors to show sources
|
||||
class VFileContent final {
|
||||
friend class FileLine;
|
||||
// MEMBERS
|
||||
int m_id; // Content ID number
|
||||
// Reference count for sharing (shared_ptr has size overhead that we don't want)
|
||||
std::atomic<size_t> m_refCount{0};
|
||||
std::deque<string> m_lines; // Source text lines
|
||||
public:
|
||||
VFileContent() {
|
||||
static int s_id = 0;
|
||||
m_id = ++s_id;
|
||||
}
|
||||
~VFileContent() = default;
|
||||
// METHODS
|
||||
void refInc() { ++m_refCount; }
|
||||
void refDec() {
|
||||
if (!--m_refCount) delete this;
|
||||
}
|
||||
|
||||
public:
|
||||
void pushText(const string& text); // Add arbitrary text (need not be line-by-line)
|
||||
string getLine(int lineno) const;
|
||||
string ascii() const { return "ct" + cvtToStr(m_id); }
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, VFileContent* contentp);
|
||||
|
||||
//! File and line number of an object, mostly for error reporting
|
||||
// File and line number of an object, mostly for error reporting
|
||||
|
||||
//! This class is instantiated for every source code line (potentially
|
||||
//! millions). To save space, per-file information (e.g. filename, source
|
||||
//! language is held in tables in the FileLineSingleton class.
|
||||
// This class is instantiated for every source code line (potentially millions), and instances
|
||||
// created at any point usually persist until the end of the program. To save space, per-file
|
||||
// information (e.g. filename, source language) is held in tables in the FileLineSingleton class.
|
||||
// Similarly, message enablement flags are interned in FileLineSingleton.
|
||||
|
||||
// WARNING: Avoid increasing the size of this class as much as possible.
|
||||
class FileLine final {
|
||||
|
||||
// CONSTANTS
|
||||
static constexpr unsigned SHOW_SOURCE_MAX_LENGTH = 400; // Don't show source lines > this long
|
||||
|
||||
// TYPES
|
||||
using fileNameIdx_t = FileLineSingleton::fileNameIdx_t;
|
||||
using msgEnSetIdx_t = FileLineSingleton::msgEnSetIdx_t;
|
||||
using MsgEnBitSet = FileLineSingleton::MsgEnBitSet;
|
||||
|
||||
// MEMBERS
|
||||
// Columns here means number of chars from beginning (i.e. tabs count as one)
|
||||
msgEnSetIdx_t m_msgEnIdx = 0; // Message enable bit set (index into interned array)
|
||||
fileNameIdx_t m_filenameno = 0; // `line corrected filename number
|
||||
bool m_waive : 1; // Waive warning - pack next to the line number to save 8 bytes of storage
|
||||
unsigned m_contentLineno : 31; // Line number within source stream
|
||||
int m_firstLineno = 0; // `line corrected token's first line number
|
||||
int m_firstColumn = 0; // `line corrected token's first column number
|
||||
int m_lastLineno = 0; // `line corrected token's last line number
|
||||
int m_lastColumn = 0; // `line corrected token's last column number
|
||||
int m_filenameno; // `line corrected filename number
|
||||
int m_contentLineno = 0; // Line number within source stream
|
||||
std::shared_ptr<VFileContent> m_contentp = nullptr; // Source text contents line is within
|
||||
VFileContent* m_contentp = nullptr; // Source text contents line is within
|
||||
FileLine* m_parent = nullptr; // Parent line that included this line
|
||||
std::bitset<V3ErrorCode::_ENUM_MAX> m_warnOn;
|
||||
bool m_waive = false; // Waive warning
|
||||
|
||||
protected:
|
||||
// User routines should never need to change line numbers
|
||||
@ -118,30 +162,38 @@ private:
|
||||
return s;
|
||||
}
|
||||
static FileLine& defaultFileLine() {
|
||||
static FileLine* defFilelinep = new FileLine(FileLine::EmptySecret());
|
||||
return *defFilelinep;
|
||||
static FileLine s;
|
||||
return s;
|
||||
}
|
||||
|
||||
FileLine() // Only used for defaultFileLine above
|
||||
: m_msgEnIdx{singleton().defaultMsgEnIndex()}
|
||||
, m_filenameno{singleton().nameToNumber(FileLine::builtInFilename())}
|
||||
, m_waive{false}
|
||||
, m_contentLineno{0} {}
|
||||
|
||||
public:
|
||||
explicit FileLine(const string& filename)
|
||||
: m_filenameno{singleton().nameToNumber(filename)}
|
||||
, m_warnOn{defaultFileLine().m_warnOn} {}
|
||||
: m_msgEnIdx{defaultFileLine().m_msgEnIdx}
|
||||
, m_filenameno{singleton().nameToNumber(filename)}
|
||||
, m_waive{false}
|
||||
, m_contentLineno{0} {}
|
||||
explicit FileLine(FileLine* fromp)
|
||||
: m_firstLineno{fromp->m_firstLineno}
|
||||
: m_msgEnIdx{fromp->m_msgEnIdx}
|
||||
, m_filenameno{fromp->m_filenameno}
|
||||
, m_waive{fromp->m_waive}
|
||||
, m_contentLineno{fromp->m_contentLineno}
|
||||
, m_firstLineno{fromp->m_firstLineno}
|
||||
, m_firstColumn{fromp->m_firstColumn}
|
||||
, m_lastLineno{fromp->m_lastLineno}
|
||||
, m_lastColumn{fromp->m_lastColumn}
|
||||
, m_filenameno{fromp->m_filenameno}
|
||||
, m_contentLineno{fromp->m_contentLineno}
|
||||
, m_contentp{fromp->m_contentp}
|
||||
, m_parent{fromp->m_parent}
|
||||
, m_warnOn{fromp->m_warnOn}
|
||||
, m_waive{fromp->m_waive} {}
|
||||
struct EmptySecret {}; // Constructor selection
|
||||
explicit FileLine(EmptySecret);
|
||||
, m_parent{fromp->m_parent} {
|
||||
if (m_contentp) m_contentp->refInc();
|
||||
}
|
||||
FileLine* copyOrSameFileLine();
|
||||
static void deleteAllRemaining();
|
||||
~FileLine() = default;
|
||||
~FileLine();
|
||||
#ifdef VL_LEAK_CHECKS
|
||||
static void* operator new(size_t size);
|
||||
static void operator delete(void* obj, size_t size);
|
||||
@ -150,7 +202,7 @@ public:
|
||||
void newContent();
|
||||
void contentLineno(int num) {
|
||||
lineno(num);
|
||||
m_contentLineno = num;
|
||||
m_contentLineno = static_cast<unsigned>(num);
|
||||
}
|
||||
void lineno(int num) {
|
||||
m_firstLineno = num;
|
||||
@ -180,7 +232,7 @@ public:
|
||||
int firstColumn() const { return m_firstColumn; }
|
||||
int lastLineno() const { return m_lastLineno; }
|
||||
int lastColumn() const { return m_lastColumn; }
|
||||
std::shared_ptr<VFileContent> contentp() const { return m_contentp; }
|
||||
VFileContent* contentp() const { return m_contentp; }
|
||||
// If not otherwise more specific, use last lineno for errors etc,
|
||||
// as the parser errors etc generally make more sense pointing at the last parse point
|
||||
int lineno() const { return m_lastLineno; }
|
||||
@ -204,24 +256,26 @@ public:
|
||||
string lineDirectiveStrg(int enterExit) const;
|
||||
|
||||
// Turn on/off warning messages on this line.
|
||||
void warnOn(V3ErrorCode code, bool flag) { m_warnOn.set(code, flag); }
|
||||
void warnOn(V3ErrorCode code, bool flag) {
|
||||
m_msgEnIdx = singleton().msgEnSetBit(m_msgEnIdx, code, flag);
|
||||
}
|
||||
void warnOff(V3ErrorCode code, bool flag) { warnOn(code, !flag); }
|
||||
bool warnOff(const string& msg, bool flag); // Returns 1 if ok
|
||||
bool warnIsOff(V3ErrorCode code) const;
|
||||
void warnLintOff(bool flag);
|
||||
void warnStyleOff(bool flag);
|
||||
void warnStateFrom(const FileLine& from) { m_warnOn = from.m_warnOn; }
|
||||
void warnStateFrom(const FileLine& from) { m_msgEnIdx = from.m_msgEnIdx; }
|
||||
void warnResetDefault() { warnStateFrom(defaultFileLine()); }
|
||||
bool lastWarnWaived() const { return m_waive; }
|
||||
|
||||
// Specific flag ACCESSORS/METHODS
|
||||
bool celldefineOn() const { return m_warnOn.test(V3ErrorCode::I_CELLDEFINE); }
|
||||
bool celldefineOn() const { return msgEn().test(V3ErrorCode::I_CELLDEFINE); }
|
||||
void celldefineOn(bool flag) { warnOn(V3ErrorCode::I_CELLDEFINE, flag); }
|
||||
bool coverageOn() const { return m_warnOn.test(V3ErrorCode::I_COVERAGE); }
|
||||
bool coverageOn() const { return msgEn().test(V3ErrorCode::I_COVERAGE); }
|
||||
void coverageOn(bool flag) { warnOn(V3ErrorCode::I_COVERAGE, flag); }
|
||||
bool tracingOn() const { return m_warnOn.test(V3ErrorCode::I_TRACING); }
|
||||
bool tracingOn() const { return msgEn().test(V3ErrorCode::I_TRACING); }
|
||||
void tracingOn(bool flag) { warnOn(V3ErrorCode::I_TRACING, flag); }
|
||||
bool timingOn() const { return m_warnOn.test(V3ErrorCode::I_TIMING); }
|
||||
bool timingOn() const { return msgEn().test(V3ErrorCode::I_TIMING); }
|
||||
void timingOn(bool flag) { warnOn(V3ErrorCode::I_TIMING, flag); }
|
||||
|
||||
// METHODS - Global
|
||||
@ -240,7 +294,9 @@ public:
|
||||
|
||||
// METHODS - Called from netlist
|
||||
// Merge warning disables from another fileline
|
||||
void modifyStateInherit(const FileLine* fromp);
|
||||
void modifyStateInherit(const FileLine* fromp) {
|
||||
m_msgEnIdx = singleton().msgEnAnd(m_msgEnIdx, fromp->m_msgEnIdx);
|
||||
}
|
||||
// Change the current fileline due to actions discovered after parsing
|
||||
// and may have side effects on other nodes sharing this FileLine.
|
||||
// Use only when this is intended
|
||||
@ -268,7 +324,7 @@ public:
|
||||
bool operator==(const FileLine& rhs) const {
|
||||
return (m_firstLineno == rhs.m_firstLineno && m_firstColumn == rhs.m_firstColumn
|
||||
&& m_lastLineno == rhs.m_lastLineno && m_lastColumn == rhs.m_lastColumn
|
||||
&& m_filenameno == rhs.m_filenameno && m_warnOn == rhs.m_warnOn);
|
||||
&& m_filenameno == rhs.m_filenameno && m_msgEnIdx == rhs.m_msgEnIdx);
|
||||
}
|
||||
// Returns -1 if (*this) should come before rhs after sorted. 1 for the opposite case. 0 for
|
||||
// equivalent.
|
||||
@ -280,14 +336,15 @@ public:
|
||||
return (m_firstColumn < rhs.m_firstColumn) ? -1 : 1;
|
||||
if (m_lastLineno != rhs.m_lastLineno) return (m_lastLineno < rhs.m_lastLineno) ? -1 : 1;
|
||||
if (m_lastColumn != rhs.m_lastColumn) return (m_lastColumn < rhs.m_lastColumn) ? -1 : 1;
|
||||
for (size_t i = 0; i < m_warnOn.size(); ++i) {
|
||||
if (m_warnOn[i] != rhs.m_warnOn[i]) return (m_warnOn[i] < rhs.m_warnOn[i]) ? -1 : 1;
|
||||
for (size_t i = 0; i < msgEn().size(); ++i) {
|
||||
if (msgEn().test(i) != rhs.msgEn().test(i)) return rhs.msgEn().test(i) ? -1 : 1;
|
||||
}
|
||||
return 0; // (*this) and rhs are equivalent
|
||||
}
|
||||
|
||||
private:
|
||||
string warnContext(bool secondary) const;
|
||||
const MsgEnBitSet& msgEn() const { return singleton().msgEn(m_msgEnIdx); }
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, FileLine* fileline);
|
||||
|
||||
|
@ -130,6 +130,7 @@ class LifeBlock final {
|
||||
LifeMap m_map; // Current active lifetime map for current scope
|
||||
LifeBlock* const m_aboveLifep; // Upper life, or nullptr
|
||||
LifeState* const m_statep; // Current global state
|
||||
bool m_replacedVref = false; // Replaced a variable reference since last clearing
|
||||
|
||||
public:
|
||||
LifeBlock(LifeBlock* aboveLifep, LifeState* statep)
|
||||
@ -178,6 +179,8 @@ public:
|
||||
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::COMPLEXASSIGN{}});
|
||||
}
|
||||
}
|
||||
void clearReplaced() { m_replacedVref = false; }
|
||||
bool replaced() const { return m_replacedVref; }
|
||||
void varUsageReplace(AstVarScope* nodep, AstVarRef* varrefp) {
|
||||
// Variable rvalue. If it references a constant, we can replace it
|
||||
const auto it = m_map.find(nodep);
|
||||
@ -188,6 +191,7 @@ public:
|
||||
// We'll later constant propagate
|
||||
UINFO(4, " replaceconst: " << varrefp << endl);
|
||||
varrefp->replaceWith(constp->cloneTree(false));
|
||||
m_replacedVref = true;
|
||||
VL_DO_DANGLING(varrefp->deleteTree(), varrefp);
|
||||
++m_statep->m_statAssnCon;
|
||||
return; // **DONE, no longer a var reference**
|
||||
@ -313,10 +317,10 @@ private:
|
||||
}
|
||||
// Collect any used variables first, as lhs may also be on rhs
|
||||
// Similar code in V3Dead
|
||||
const uint64_t lastEdit = AstNode::editCountGbl(); // When it was last edited
|
||||
m_sideEffect = false;
|
||||
m_lifep->clearReplaced();
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
if (lastEdit != AstNode::editCountGbl()) {
|
||||
if (m_lifep->replaced()) {
|
||||
// We changed something, try to constant propagate, but don't delete the
|
||||
// assignment as we still need nodep to remain.
|
||||
V3Const::constifyEdit(nodep->rhsp()); // rhsp may change
|
||||
|
@ -101,7 +101,7 @@ public:
|
||||
for (V3HierarchicalBlockOption::ParamStrMap::const_iterator pIt = params.begin();
|
||||
pIt != params.end(); ++pIt) {
|
||||
std::unique_ptr<AstConst> constp{AstConst::parseParamLiteral(
|
||||
new FileLine(FileLine::EmptySecret()), pIt->second)};
|
||||
new FileLine{FileLine::builtInFilename()}, pIt->second)};
|
||||
UASSERT(constp, pIt->second << " is not a valid parameter literal");
|
||||
const bool inserted = consts.emplace(pIt->first, std::move(constp)).second;
|
||||
UASSERT(inserted, pIt->first << " is already added");
|
||||
|
Loading…
Reference in New Issue
Block a user