Reduce size of FileLine
Multiple tricks to reduce the size of class FileLine from 72 to 40 bytes: - Reduce file name index from 32 to 16 bits. This still allows 64K unique input files, which is hopefully enough. - Intern message/warning enable bitset and use a 16-bit index, again allowing 64K unique sets which is hopefully enough. - Put the m_waive flag into the sign bit of one of the line numbers. - Use explicit reference counting to avoid overhead of shared_ptr. Added assertions to ensure interned data fits within it's index space. This saves ~5-10% peak memory consumption at no measurable run-time cost on various designs.
This commit is contained in:
parent
2f50642ecb
commit
78e659a142
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <limits>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
|
|
@ -38,7 +39,7 @@ VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// FileLineSingleton class functions
|
// FileLineSingleton class functions
|
||||||
|
|
||||||
string FileLineSingleton::filenameLetters(int fileno) {
|
string FileLineSingleton::filenameLetters(fileNameIdx_t fileno) {
|
||||||
constexpr int size
|
constexpr int size
|
||||||
= 1 + (64 / 4); // Each letter retires more than 4 bits of a > 64 bit number
|
= 1 + (64 / 4); // Each letter retires more than 4 bits of a > 64 bit number
|
||||||
char out[size];
|
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
|
//! We associate a language with each source file, so we also set the default
|
||||||
//! for this.
|
//! for this.
|
||||||
int FileLineSingleton::nameToNumber(const string& filename) {
|
FileLineSingleton::fileNameIdx_t FileLineSingleton::nameToNumber(const string& filename) {
|
||||||
const auto it = vlstd::as_const(m_namemap).find(filename);
|
const auto pair = m_namemap.emplace(filename, 0);
|
||||||
if (VL_LIKELY(it != m_namemap.end())) return it->second;
|
fileNameIdx_t& idx = pair.first->second;
|
||||||
const int num = m_names.size();
|
if (pair.second) {
|
||||||
m_names.push_back(filename);
|
const size_t nextIdx = m_names.size();
|
||||||
m_languages.push_back(V3LangCode::mostRecent());
|
UASSERT(nextIdx <= std::numeric_limits<fileNameIdx_t>::max(),
|
||||||
m_namemap.emplace(filename, num);
|
"Too many input files (" + cvtToStr(nextIdx) + "+).");
|
||||||
return num;
|
idx = static_cast<fileNameIdx_t>(nextIdx);
|
||||||
|
m_names.push_back(filename);
|
||||||
|
m_languages.push_back(V3LangCode::mostRecent());
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Support XML output
|
//! Support XML output
|
||||||
|
|
@ -82,8 +87,46 @@ void FileLineSingleton::fileNameNumMapDumpXml(std::ostream& os) {
|
||||||
os << "</files>\n";
|
os << "</files>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
FileLineSingleton::msgEnSetIdx_t FileLineSingleton::addMsgEnBitSet(const MsgEnBitSet& bitSet) {
|
||||||
// VFileContents class functions
|
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) {
|
void VFileContent::pushText(const string& text) {
|
||||||
if (m_lines.size() == 0) {
|
if (m_lines.size() == 0) {
|
||||||
|
|
@ -136,22 +179,17 @@ std::ostream& operator<<(std::ostream& os, VFileContent* contentp) {
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
// ######################################################################
|
||||||
// FileLine class functions
|
// FileLine class functions
|
||||||
|
|
||||||
// Sort of a singleton
|
FileLine::~FileLine() {
|
||||||
FileLine::FileLine(FileLine::EmptySecret) {
|
if (m_contentp) VL_DO_DANGLING(m_contentp->refDec(), m_contentp);
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLine::newContent() {
|
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;
|
m_contentLineno = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -318,24 +356,16 @@ void FileLine::warnStyleOff(bool flag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileLine::warnIsOff(V3ErrorCode code) const {
|
bool FileLine::warnIsOff(V3ErrorCode code) const {
|
||||||
if (!m_warnOn.test(code)) return true;
|
if (!msgEn().test(code)) return true;
|
||||||
if (!defaultFileLine().m_warnOn.test(code)) return true; // Global overrides local
|
if (!defaultFileLine().msgEn().test(code)) return true; // Global overrides local
|
||||||
// UNOPTFLAT implies UNOPT
|
// UNOPTFLAT implies UNOPT
|
||||||
if (code == V3ErrorCode::UNOPT && !m_warnOn.test(V3ErrorCode::UNOPTFLAT)) return true;
|
if (code == V3ErrorCode::UNOPT && !msgEn().test(V3ErrorCode::UNOPTFLAT)) return true;
|
||||||
if ((code.lintError() || code.styleError()) && !m_warnOn.test(V3ErrorCode::I_LINT)) {
|
if ((code.lintError() || code.styleError()) && !msgEn().test(V3ErrorCode::I_LINT)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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) {
|
void FileLine::v3errorEnd(std::ostringstream& sstr, const string& extra) {
|
||||||
std::ostringstream nsstr;
|
std::ostringstream nsstr;
|
||||||
if (lastLineno()) nsstr << this;
|
if (lastLineno()) nsstr << this;
|
||||||
|
|
|
||||||
145
src/V3FileLine.h
145
src/V3FileLine.h
|
|
@ -23,14 +23,17 @@
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3LangCode.h"
|
#include "V3LangCode.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
//######################################################################
|
// ######################################################################
|
||||||
|
|
||||||
class FileLine;
|
class FileLine;
|
||||||
|
|
||||||
|
|
@ -39,68 +42,109 @@ class FileLine;
|
||||||
//! This singleton class contains tables of data that are unchanging in each
|
//! This singleton class contains tables of data that are unchanging in each
|
||||||
//! source file (each with its own unique filename number).
|
//! source file (each with its own unique filename number).
|
||||||
class FileLineSingleton final {
|
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
|
// 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<string> m_names; // filename text for each filenameno
|
||||||
std::deque<V3LangCode> m_languages; // language 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
|
// CONSTRUCTORS
|
||||||
FileLineSingleton() = default;
|
FileLineSingleton() = default;
|
||||||
~FileLineSingleton() = default;
|
~FileLineSingleton() = default;
|
||||||
|
|
||||||
protected:
|
fileNameIdx_t nameToNumber(const string& filename);
|
||||||
friend class FileLine;
|
string numberToName(fileNameIdx_t filenameno) const { return m_names[filenameno]; }
|
||||||
int nameToNumber(const string& filename);
|
V3LangCode numberToLang(fileNameIdx_t filenameno) const { return m_languages[filenameno]; }
|
||||||
string numberToName(int filenameno) const { return m_names[filenameno]; }
|
void numberToLang(fileNameIdx_t filenameno, const V3LangCode& l) {
|
||||||
V3LangCode numberToLang(int filenameno) const { return m_languages[filenameno]; }
|
m_languages[filenameno] = l;
|
||||||
void numberToLang(int filenameno, const V3LangCode& l) { m_languages[filenameno] = l; }
|
}
|
||||||
void clear() {
|
void clear() {
|
||||||
m_namemap.clear();
|
m_namemap.clear();
|
||||||
m_names.clear();
|
m_names.clear();
|
||||||
m_languages.clear();
|
m_languages.clear();
|
||||||
}
|
}
|
||||||
void fileNameNumMapDumpXml(std::ostream& os);
|
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 {
|
class VFileContent final {
|
||||||
|
friend class FileLine;
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
int m_id; // Content ID number
|
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
|
std::deque<string> m_lines; // Source text lines
|
||||||
public:
|
|
||||||
VFileContent() {
|
VFileContent() {
|
||||||
static int s_id = 0;
|
static int s_id = 0;
|
||||||
m_id = ++s_id;
|
m_id = ++s_id;
|
||||||
}
|
}
|
||||||
~VFileContent() = default;
|
~VFileContent() = default;
|
||||||
// METHODS
|
// 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)
|
void pushText(const string& text); // Add arbitrary text (need not be line-by-line)
|
||||||
string getLine(int lineno) const;
|
string getLine(int lineno) const;
|
||||||
string ascii() const { return "ct" + cvtToStr(m_id); }
|
string ascii() const { return "ct" + cvtToStr(m_id); }
|
||||||
};
|
};
|
||||||
std::ostream& operator<<(std::ostream& os, VFileContent* contentp);
|
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
|
// This class is instantiated for every source code line (potentially millions), and instances
|
||||||
//! millions). To save space, per-file information (e.g. filename, source
|
// created at any point usually persist until the end of the program. To save space, per-file
|
||||||
//! language is held in tables in the FileLineSingleton class.
|
// 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 {
|
class FileLine final {
|
||||||
|
|
||||||
// CONSTANTS
|
// CONSTANTS
|
||||||
static constexpr unsigned SHOW_SOURCE_MAX_LENGTH = 400; // Don't show source lines > this long
|
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
|
// MEMBERS
|
||||||
// Columns here means number of chars from beginning (i.e. tabs count as one)
|
// 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_firstLineno = 0; // `line corrected token's first line number
|
||||||
int m_firstColumn = 0; // `line corrected token's first column 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_lastLineno = 0; // `line corrected token's last line number
|
||||||
int m_lastColumn = 0; // `line corrected token's last column number
|
int m_lastColumn = 0; // `line corrected token's last column number
|
||||||
int m_filenameno; // `line corrected filename number
|
VFileContent* m_contentp = nullptr; // Source text contents line is within
|
||||||
int m_contentLineno = 0; // Line number within source stream
|
|
||||||
std::shared_ptr<VFileContent> m_contentp = nullptr; // Source text contents line is within
|
|
||||||
FileLine* m_parent = nullptr; // Parent line that included this line
|
FileLine* m_parent = nullptr; // Parent line that included this line
|
||||||
std::bitset<V3ErrorCode::_ENUM_MAX> m_warnOn;
|
|
||||||
bool m_waive = false; // Waive warning
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// User routines should never need to change line numbers
|
// User routines should never need to change line numbers
|
||||||
|
|
@ -118,30 +162,38 @@ private:
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
static FileLine& defaultFileLine() {
|
static FileLine& defaultFileLine() {
|
||||||
static FileLine* defFilelinep = new FileLine(FileLine::EmptySecret());
|
static FileLine s;
|
||||||
return *defFilelinep;
|
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:
|
public:
|
||||||
explicit FileLine(const string& filename)
|
explicit FileLine(const string& filename)
|
||||||
: m_filenameno{singleton().nameToNumber(filename)}
|
: m_msgEnIdx{defaultFileLine().m_msgEnIdx}
|
||||||
, m_warnOn{defaultFileLine().m_warnOn} {}
|
, m_filenameno{singleton().nameToNumber(filename)}
|
||||||
|
, m_waive{false}
|
||||||
|
, m_contentLineno{0} {}
|
||||||
explicit FileLine(FileLine* fromp)
|
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_firstColumn{fromp->m_firstColumn}
|
||||||
, m_lastLineno{fromp->m_lastLineno}
|
, m_lastLineno{fromp->m_lastLineno}
|
||||||
, m_lastColumn{fromp->m_lastColumn}
|
, m_lastColumn{fromp->m_lastColumn}
|
||||||
, m_filenameno{fromp->m_filenameno}
|
|
||||||
, m_contentLineno{fromp->m_contentLineno}
|
|
||||||
, m_contentp{fromp->m_contentp}
|
, m_contentp{fromp->m_contentp}
|
||||||
, m_parent{fromp->m_parent}
|
, m_parent{fromp->m_parent} {
|
||||||
, m_warnOn{fromp->m_warnOn}
|
if (m_contentp) m_contentp->refInc();
|
||||||
, m_waive{fromp->m_waive} {}
|
}
|
||||||
struct EmptySecret {}; // Constructor selection
|
|
||||||
explicit FileLine(EmptySecret);
|
|
||||||
FileLine* copyOrSameFileLine();
|
FileLine* copyOrSameFileLine();
|
||||||
static void deleteAllRemaining();
|
static void deleteAllRemaining();
|
||||||
~FileLine() = default;
|
~FileLine();
|
||||||
#ifdef VL_LEAK_CHECKS
|
#ifdef VL_LEAK_CHECKS
|
||||||
static void* operator new(size_t size);
|
static void* operator new(size_t size);
|
||||||
static void operator delete(void* obj, size_t size);
|
static void operator delete(void* obj, size_t size);
|
||||||
|
|
@ -150,7 +202,7 @@ public:
|
||||||
void newContent();
|
void newContent();
|
||||||
void contentLineno(int num) {
|
void contentLineno(int num) {
|
||||||
lineno(num);
|
lineno(num);
|
||||||
m_contentLineno = num;
|
m_contentLineno = static_cast<unsigned>(num);
|
||||||
}
|
}
|
||||||
void lineno(int num) {
|
void lineno(int num) {
|
||||||
m_firstLineno = num;
|
m_firstLineno = num;
|
||||||
|
|
@ -180,7 +232,7 @@ public:
|
||||||
int firstColumn() const { return m_firstColumn; }
|
int firstColumn() const { return m_firstColumn; }
|
||||||
int lastLineno() const { return m_lastLineno; }
|
int lastLineno() const { return m_lastLineno; }
|
||||||
int lastColumn() const { return m_lastColumn; }
|
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,
|
// 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
|
// as the parser errors etc generally make more sense pointing at the last parse point
|
||||||
int lineno() const { return m_lastLineno; }
|
int lineno() const { return m_lastLineno; }
|
||||||
|
|
@ -204,22 +256,24 @@ public:
|
||||||
string lineDirectiveStrg(int enterExit) const;
|
string lineDirectiveStrg(int enterExit) const;
|
||||||
|
|
||||||
// Turn on/off warning messages on this line.
|
// 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); }
|
void warnOff(V3ErrorCode code, bool flag) { warnOn(code, !flag); }
|
||||||
bool warnOff(const string& msg, bool flag); // Returns 1 if ok
|
bool warnOff(const string& msg, bool flag); // Returns 1 if ok
|
||||||
bool warnIsOff(V3ErrorCode code) const;
|
bool warnIsOff(V3ErrorCode code) const;
|
||||||
void warnLintOff(bool flag);
|
void warnLintOff(bool flag);
|
||||||
void warnStyleOff(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()); }
|
void warnResetDefault() { warnStateFrom(defaultFileLine()); }
|
||||||
bool lastWarnWaived() const { return m_waive; }
|
bool lastWarnWaived() const { return m_waive; }
|
||||||
|
|
||||||
// Specific flag ACCESSORS/METHODS
|
// 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); }
|
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); }
|
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); }
|
void tracingOn(bool flag) { warnOn(V3ErrorCode::I_TRACING, flag); }
|
||||||
|
|
||||||
// METHODS - Global
|
// METHODS - Global
|
||||||
|
|
@ -238,7 +292,9 @@ public:
|
||||||
|
|
||||||
// METHODS - Called from netlist
|
// METHODS - Called from netlist
|
||||||
// Merge warning disables from another fileline
|
// 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
|
// Change the current fileline due to actions discovered after parsing
|
||||||
// and may have side effects on other nodes sharing this FileLine.
|
// and may have side effects on other nodes sharing this FileLine.
|
||||||
// Use only when this is intended
|
// Use only when this is intended
|
||||||
|
|
@ -266,7 +322,7 @@ public:
|
||||||
bool operator==(const FileLine& rhs) const {
|
bool operator==(const FileLine& rhs) const {
|
||||||
return (m_firstLineno == rhs.m_firstLineno && m_firstColumn == rhs.m_firstColumn
|
return (m_firstLineno == rhs.m_firstLineno && m_firstColumn == rhs.m_firstColumn
|
||||||
&& m_lastLineno == rhs.m_lastLineno && m_lastColumn == rhs.m_lastColumn
|
&& 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
|
// Returns -1 if (*this) should come before rhs after sorted. 1 for the opposite case. 0 for
|
||||||
// equivalent.
|
// equivalent.
|
||||||
|
|
@ -278,14 +334,15 @@ public:
|
||||||
return (m_firstColumn < rhs.m_firstColumn) ? -1 : 1;
|
return (m_firstColumn < rhs.m_firstColumn) ? -1 : 1;
|
||||||
if (m_lastLineno != rhs.m_lastLineno) return (m_lastLineno < rhs.m_lastLineno) ? -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;
|
if (m_lastColumn != rhs.m_lastColumn) return (m_lastColumn < rhs.m_lastColumn) ? -1 : 1;
|
||||||
for (size_t i = 0; i < m_warnOn.size(); ++i) {
|
for (size_t i = 0; i < msgEn().size(); ++i) {
|
||||||
if (m_warnOn[i] != rhs.m_warnOn[i]) return (m_warnOn[i] < rhs.m_warnOn[i]) ? -1 : 1;
|
if (msgEn().test(i) != rhs.msgEn().test(i)) return rhs.msgEn().test(i) ? -1 : 1;
|
||||||
}
|
}
|
||||||
return 0; // (*this) and rhs are equivalent
|
return 0; // (*this) and rhs are equivalent
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string warnContext(bool secondary) const;
|
string warnContext(bool secondary) const;
|
||||||
|
const MsgEnBitSet& msgEn() const { return singleton().msgEn(m_msgEnIdx); }
|
||||||
};
|
};
|
||||||
std::ostream& operator<<(std::ostream& os, FileLine* fileline);
|
std::ostream& operator<<(std::ostream& os, FileLine* fileline);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ public:
|
||||||
for (V3HierarchicalBlockOption::ParamStrMap::const_iterator pIt = params.begin();
|
for (V3HierarchicalBlockOption::ParamStrMap::const_iterator pIt = params.begin();
|
||||||
pIt != params.end(); ++pIt) {
|
pIt != params.end(); ++pIt) {
|
||||||
std::unique_ptr<AstConst> constp{AstConst::parseParamLiteral(
|
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");
|
UASSERT(constp, pIt->second << " is not a valid parameter literal");
|
||||||
const bool inserted = consts.emplace(pIt->first, std::move(constp)).second;
|
const bool inserted = consts.emplace(pIt->first, std::move(constp)).second;
|
||||||
UASSERT(inserted, pIt->first << " is already added");
|
UASSERT(inserted, pIt->first << " is already added");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue