Internals: Improve cppcheck flow and fix up issues (#6311)
Added cppcheck-suppressions.txt in the repo root. You can add new patterns in there instead of having to parse the XML output. Also configure to add the -D__GNUC__ preprocessor macro, which makes it understand UASSERT (it understands the 'noreturn' function attribute). Added some case by case specific suppressions and fixed up other code, especially in V3Ast*h and V3Dfg*.h, including code generated by astgen that had some no-ops that irks cppcheck. One thing it does not seem to like is `const` class members with default initializers in the class. It will assume that's always the value, even if overridden in the constructor. We had few so removed them. With that a lot of files in `src/` are now clean or only have a handful of issues. Therefore, I have also deleted cppcheck_filtered, and made it produce human readable output straight to the terminal. Regarding cleaning up the reported nits, I kind of got bored after V3[A-E] so pausing here. Apologies for the merge conflicts. Tested with cppcheck 2.13.0
This commit is contained in:
parent
636a6b8cd2
commit
a0edd4e907
58
Makefile.in
58
Makefile.in
|
|
@ -409,36 +409,39 @@ CHECK_H = $(wildcard \
|
|||
CHECK_YL = $(wildcard \
|
||||
$(srcdir)/src/*.y \
|
||||
$(srcdir)/src/*.l )
|
||||
CPPCHECK = src/cppcheck_filtered cppcheck
|
||||
CPPCHECK_FLAGS = --enable=all --inline-suppr \
|
||||
--suppress=cstyleCast --suppress=ctunullpointer \
|
||||
--suppress=derefInvalidIteratorRedundantCheck \
|
||||
--suppress=nullPointer --suppress=nullPointerRedundantCheck \
|
||||
--suppress=templateRecursion \
|
||||
--suppress=unusedFunction --suppress=unusedScopedObject \
|
||||
--suppress=useInitializationList --suppress=useStlAlgorithm \
|
||||
CPPCHECK = cppcheck
|
||||
CPPCHECK_CACHE = $(srcdir)/src/obj_dbg/cppcheck-cache
|
||||
CPPCHECK_FLAGS = --enable=all
|
||||
CPPCHECK_FLAGS += --inline-suppr
|
||||
CPPCHECK_FLAGS += --suppressions-list=$(srcdir)/src/cppcheck-suppressions.txt
|
||||
CPPCHECK_FLAGS += --cppcheck-build-dir=$(CPPCHECK_CACHE)
|
||||
CPPCHECK_FLAGS += -DVL_DEBUG=1 -DVL_CPPCHECK=1 -D__GNUC__=1
|
||||
CPPCHECK_INC = -I$(srcdir)/include
|
||||
CPPCHECK_INC += -I$(srcdir)/include/gtkwave
|
||||
CPPCHECK_INC += -I$(srcdir)/include/vltstd
|
||||
CPPCHECK_INC += -I$(srcdir)/src/obj_dbg
|
||||
CPPCHECK_INC += -I$(srcdir)/src
|
||||
|
||||
CPPCHECK_FLAGS += --xml
|
||||
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CHECK_CPP))
|
||||
CPPCHECK_INC = -I$(srcdir)/include -I$(srcdir)/include/gtkwave -I$(srcdir)/include/vltstd -I$(srcdir)/src/obj_dbg -I$(srcdir)/src
|
||||
$(CPPCHECK_CACHE):
|
||||
mkdir -p $@
|
||||
|
||||
cppcheck: cppcheck-1 cppcheck-2 cppcheck-3 cppcheck-4 cppcheck-5 cppcheck-6 cppcheck-7 cppcheck-8
|
||||
cppcheck-1:
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK1_CPP)
|
||||
cppcheck-2:
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK2_CPP)
|
||||
cppcheck-3:
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK3_CPP)
|
||||
cppcheck-4:
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK4_CPP)
|
||||
cppcheck-5:
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK5_CPP)
|
||||
cppcheck-6:
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK6_CPP)
|
||||
cppcheck-7:
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK7_CPP)
|
||||
cppcheck-8:
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK8_CPP)
|
||||
cppcheck-1: | $(CPPCHECK_CACHE)
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK1_CPP)
|
||||
cppcheck-2: | $(CPPCHECK_CACHE)
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK2_CPP)
|
||||
cppcheck-3: | $(CPPCHECK_CACHE)
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK3_CPP)
|
||||
cppcheck-4: | $(CPPCHECK_CACHE)
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK4_CPP)
|
||||
cppcheck-5: | $(CPPCHECK_CACHE)
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK5_CPP)
|
||||
cppcheck-6: | $(CPPCHECK_CACHE)
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK6_CPP)
|
||||
cppcheck-7: | $(CPPCHECK_CACHE)
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK7_CPP)
|
||||
cppcheck-8: | $(CPPCHECK_CACHE)
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK8_CPP)
|
||||
|
||||
CLANGTIDY = clang-tidy
|
||||
CLANGTIDY_FLAGS = -config='' \
|
||||
|
|
@ -512,7 +515,6 @@ PY_PROGRAMS = \
|
|||
src/astgen \
|
||||
src/bisonpre \
|
||||
src/config_rev \
|
||||
src/cppcheck_filtered \
|
||||
src/flexfix \
|
||||
src/vlcovgen \
|
||||
src/.gdbinit.py \
|
||||
|
|
|
|||
|
|
@ -52,15 +52,13 @@
|
|||
// clang and gcc-8.0+ support no_sanitize("string") style attribute
|
||||
# if defined(__clang__) || (__GNUC__ >= 8)
|
||||
# define VL_ATTR_NO_SANITIZE_ALIGN __attribute__((no_sanitize("alignment")))
|
||||
#else // The entire undefined sanitizer has to be disabled for older gcc
|
||||
# else // The entire undefined sanitizer has to be disabled for older gcc
|
||||
# define VL_ATTR_NO_SANITIZE_ALIGN __attribute__((no_sanitize_undefined))
|
||||
#endif
|
||||
# endif
|
||||
# define VL_ATTR_PRINTF(fmtArgNum) __attribute__((format(printf, (fmtArgNum), (fmtArgNum) + 1)))
|
||||
# define VL_ATTR_PURE __attribute__((pure))
|
||||
# define VL_ATTR_UNUSED __attribute__((unused))
|
||||
#ifndef VL_ATTR_WARN_UNUSED_RESULT
|
||||
# define VL_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#endif
|
||||
# if !defined(_WIN32) && !defined(__MINGW32__)
|
||||
// All VL_ATTR_WEAK symbols must be marked with the macOS -U linker flag in verilated.mk.in
|
||||
# define VL_ATTR_WEAK __attribute__((weak))
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ public:
|
|||
// paths make an assignment. Detected latches are flagged in the variables AstVar
|
||||
void latchCheck(AstNode* nodep, bool latch_expected) {
|
||||
bool latch_detected = false;
|
||||
for (const auto& vrp : m_outputs) {
|
||||
for (const AstVarRef* const vrp : m_outputs) {
|
||||
LatchDetectGraphVertex* const vertp = castVertexp(vrp->varp()->user1p());
|
||||
vertp->user(true); // Identify the output vertex we are checking paths _to_
|
||||
if (!latchCheckInternal(castVertexp(vertices().frontp()))) latch_detected = true;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
}
|
||||
VL_UNREACHABLE;
|
||||
}
|
||||
string assertDisplayMessage(AstNode* nodep, const string& prefix, const string& message,
|
||||
string assertDisplayMessage(const AstNode* nodep, const string& prefix, const string& message,
|
||||
VDisplayType severity) {
|
||||
if (severity == VDisplayType::DT_ERROR || severity == VDisplayType::DT_FATAL) {
|
||||
return ("[%0t] "s + prefix + ": " + nodep->fileline()->filebasename() + ":"
|
||||
|
|
@ -148,7 +148,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
sampledp->dtypeFrom(nodep);
|
||||
return sampledp;
|
||||
}
|
||||
AstVarRef* newMonitorNumVarRefp(AstNode* nodep, VAccess access) {
|
||||
AstVarRef* newMonitorNumVarRefp(const AstNode* nodep, VAccess access) {
|
||||
if (!m_monitorNumVarp) {
|
||||
m_monitorNumVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorNum",
|
||||
nodep->findUInt64DType()};
|
||||
|
|
@ -158,7 +158,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
return varrefp;
|
||||
}
|
||||
AstVarRef* newMonitorOffVarRefp(AstNode* nodep, VAccess access) {
|
||||
AstVarRef* newMonitorOffVarRefp(const AstNode* nodep, VAccess access) {
|
||||
if (!m_monitorOffVarp) {
|
||||
m_monitorOffVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorOff",
|
||||
nodep->findBitDType()};
|
||||
|
|
@ -181,7 +181,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
return newp;
|
||||
}
|
||||
|
||||
AstNodeStmt* newFireAssertUnchecked(AstNodeStmt* nodep, const string& message,
|
||||
AstNodeStmt* newFireAssertUnchecked(const AstNodeStmt* nodep, const string& message,
|
||||
AstNodeExpr* exprsp = nullptr) {
|
||||
// Like newFireAssert() but omits the asserts-on check
|
||||
AstDisplay* const dispp
|
||||
|
|
@ -194,7 +194,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
return bodysp;
|
||||
}
|
||||
|
||||
AstNodeStmt* newFireAssert(AstNodeStmt* nodep, VAssertDirectiveType directiveType,
|
||||
AstNodeStmt* newFireAssert(const AstNodeStmt* nodep, VAssertDirectiveType directiveType,
|
||||
VAssertType assertType, const string& message,
|
||||
AstNodeExpr* exprsp = nullptr) {
|
||||
AstNodeStmt* bodysp = newFireAssertUnchecked(nodep, message, exprsp);
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ private:
|
|||
}
|
||||
AstPropSpec* substitutePropertyCall(AstPropSpec* nodep) {
|
||||
if (AstFuncRef* const funcrefp = VN_CAST(nodep->propp(), FuncRef)) {
|
||||
if (AstProperty* const propp = VN_CAST(funcrefp->taskp(), Property)) {
|
||||
if (const AstProperty* const propp = VN_CAST(funcrefp->taskp(), Property)) {
|
||||
AstPropSpec* propExprp = getPropertyExprp(propp);
|
||||
// Substitute inner property call before copying in order to not doing the same for
|
||||
// each call of outer property call.
|
||||
|
|
@ -183,7 +183,7 @@ private:
|
|||
m_clockingp->addNextHere(varp->unlinkFrBack());
|
||||
varp->user1p(nodep);
|
||||
if (nodep->direction() == VDirection::OUTPUT) {
|
||||
exprp->foreach([](AstNodeVarRef* varrefp) {
|
||||
exprp->foreach([](const AstNodeVarRef* varrefp) {
|
||||
// Prevent confusing BLKANDNBLK warnings on clockvars due to generated assignments
|
||||
varrefp->fileline()->warnOff(V3ErrorCode::BLKANDNBLK, true);
|
||||
});
|
||||
|
|
@ -318,7 +318,7 @@ private:
|
|||
if (nodep->stmtsp()) nodep->addNextHere(nodep->stmtsp()->unlinkFrBackWithNext());
|
||||
FileLine* const flp = nodep->fileline();
|
||||
AstNodeExpr* valuep = V3Const::constifyEdit(nodep->lhsp()->unlinkFrBack());
|
||||
AstConst* const constp = VN_CAST(valuep, Const);
|
||||
const AstConst* const constp = VN_CAST(valuep, Const);
|
||||
if (constp->isZero()) {
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: ##0 delays");
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
|
|
|
|||
|
|
@ -255,14 +255,13 @@ string AstNode::vpiName(const string& namein) {
|
|||
// This is slightly different from prettyName, in that when we encounter escaped characters,
|
||||
// we change that identifier to an escaped identifier, wrapping it with '\' and ' '
|
||||
// as specified in LRM 23.6
|
||||
string name = namein;
|
||||
if (0 == namein.substr(0, 7).compare("__SYM__")) name = namein.substr(7);
|
||||
const size_t offset = VString::startsWith(namein, "__SYM__") ? 7 : 0;
|
||||
string pretty;
|
||||
pretty.reserve(name.length());
|
||||
pretty.reserve(namein.length());
|
||||
bool inEscapedIdent = false;
|
||||
int lastIdent = 0;
|
||||
|
||||
for (const char* pos = name.c_str(); *pos;) {
|
||||
for (const char* pos = namein.c_str() + offset; *pos;) {
|
||||
char specialChar = 0;
|
||||
if (pos[0] == '-' && pos[1] == '>') { // ->
|
||||
specialChar = '.';
|
||||
|
|
@ -280,7 +279,7 @@ string AstNode::vpiName(const string& namein) {
|
|||
} else if (0 == std::strncmp(pos, "__PVT__", 7)) {
|
||||
pos += 7;
|
||||
continue;
|
||||
} else if (pos[0] == '_' && pos[1] == '_' && pos[2] == '0' && std::isxdigit(pos[3])
|
||||
} else if (0 == std::strncmp(pos, "__0", 3) && std::isxdigit(pos[3])
|
||||
&& std::isxdigit(pos[4])) {
|
||||
char value = 0;
|
||||
value += 16
|
||||
|
|
@ -567,6 +566,7 @@ AstNode* AstNode::unlinkFrBackWithNext(VNRelinker* linkerp) {
|
|||
AstNode* const oldp = this;
|
||||
UASSERT_OBJ(oldp->m_backp, oldp, "Node has no back, already unlinked?");
|
||||
oldp->editCountInc();
|
||||
// cppcheck-suppress shadowFunction
|
||||
AstNode* const backp = oldp->m_backp;
|
||||
if (linkerp) {
|
||||
linkerp->m_oldp = oldp;
|
||||
|
|
@ -629,6 +629,7 @@ AstNode* AstNode::unlinkFrBack(VNRelinker* linkerp) {
|
|||
AstNode* const oldp = this;
|
||||
UASSERT_OBJ(oldp->m_backp, oldp, "Node has no back, already unlinked?");
|
||||
oldp->editCountInc();
|
||||
// cppcheck-suppress shadowFunction
|
||||
AstNode* const backp = oldp->m_backp;
|
||||
if (linkerp) {
|
||||
linkerp->m_oldp = oldp;
|
||||
|
|
@ -710,6 +711,7 @@ void AstNode::relink(VNRelinker* linkerp) {
|
|||
cout << endl;
|
||||
}
|
||||
|
||||
// cppcheck-suppress shadowFunction
|
||||
AstNode* const backp = linkerp->m_backp;
|
||||
debugTreeChange(this, "-relinkNew: ", __LINE__, true);
|
||||
debugTreeChange(backp, "-relinkTre: ", __LINE__, true);
|
||||
|
|
@ -773,6 +775,7 @@ void AstNode::addHereThisAsNext(AstNode* newp) {
|
|||
UASSERT_OBJ(this->m_backp, this, "'this' node has no back, already unlinked?");
|
||||
UASSERT_OBJ(newp->m_headtailp, newp, "m_headtailp not set on new node");
|
||||
//
|
||||
// cppcheck-suppress shadowFunction
|
||||
AstNode* const backp = this->m_backp;
|
||||
AstNode* const newLastp = newp->m_headtailp;
|
||||
//
|
||||
|
|
@ -1185,6 +1188,7 @@ void AstNode::checkTreeIter(const AstNode* prevBackp) const VL_MT_STABLE {
|
|||
break;
|
||||
case VNTypeInfo::OP_LIST:
|
||||
if (const AstNode* const headp = nodep) {
|
||||
// cppcheck-suppress shadowFunction
|
||||
const AstNode* backp = this;
|
||||
const AstNode* tailp;
|
||||
const AstNode* opp = headp;
|
||||
|
|
@ -1457,15 +1461,16 @@ string AstNode::instanceStr() const {
|
|||
// in case we have some circular reference bug.
|
||||
constexpr unsigned maxIterations = 10000;
|
||||
unsigned iterCount = 0;
|
||||
for (const AstNode* backp = this; backp; backp = backp->backp(), ++iterCount) {
|
||||
// Walk 'backp' chain
|
||||
for (const AstNode* currp = this; currp; currp = currp->backp(), ++iterCount) {
|
||||
if (VL_UNCOVERABLE(iterCount >= maxIterations)) return ""; // LCOV_EXCL_LINE
|
||||
// Prefer the enclosing scope, if there is one. This is always under the enclosing module,
|
||||
// so just pick it up when encountered
|
||||
if (const AstScope* const scopep = VN_CAST(backp, Scope)) {
|
||||
if (const AstScope* const scopep = VN_CAST(currp, Scope)) {
|
||||
return scopep->isTop() ? "" : "... note: In instance " + scopep->prettyNameQ();
|
||||
}
|
||||
// If scopes don't exist, report an example instance of the enclosing module
|
||||
if (const AstModule* const modp = VN_CAST(backp, Module)) {
|
||||
if (const AstModule* const modp = VN_CAST(currp, Module)) {
|
||||
const string instanceName = modp->someInstanceName();
|
||||
return instanceName.empty() ? "" : "... note: In instance '" + instanceName + "'";
|
||||
}
|
||||
|
|
@ -1619,8 +1624,8 @@ static VCastable computeCastableImp(const AstNodeDType* toDtp, const AstNodeDTyp
|
|||
} else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromConstp, Const)) {
|
||||
if (fromConstp->isNull()) return VCastable::COMPATIBLE;
|
||||
} else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromDtp, ClassRefDType)) {
|
||||
const auto toClassp = VN_AS(toDtp, ClassRefDType)->classp();
|
||||
const auto fromClassp = VN_AS(fromDtp, ClassRefDType)->classp();
|
||||
const AstClass* const toClassp = VN_AS(toDtp, ClassRefDType)->classp();
|
||||
const AstClass* const fromClassp = VN_AS(fromDtp, ClassRefDType)->classp();
|
||||
const bool downcast = AstClass::isClassExtendedFrom(toClassp, fromClassp);
|
||||
const bool upcast = AstClass::isClassExtendedFrom(fromClassp, toClassp);
|
||||
if (upcast) {
|
||||
|
|
@ -1664,7 +1669,7 @@ AstNodeDType* AstNode::getCommonClassTypep(AstNode* node1p, AstNode* node2p) {
|
|||
while (classDtypep1) {
|
||||
const VCastable castable = computeCastable(classDtypep1, node2p->dtypep(), node2p);
|
||||
if (castable == VCastable::COMPATIBLE) return classDtypep1;
|
||||
AstClassExtends* const extendsp = classDtypep1->classp()->extendsp();
|
||||
const AstClassExtends* const extendsp = classDtypep1->classp()->extendsp();
|
||||
classDtypep1 = extendsp ? VN_AS(extendsp->dtypep(), ClassRefDType) : nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
|||
21
src/V3Ast.h
21
src/V3Ast.h
|
|
@ -116,9 +116,8 @@ public:
|
|||
// Above include has:
|
||||
// enum en {...};
|
||||
// const char* ascii() const {...};
|
||||
enum en m_e;
|
||||
// cppcheck-suppress uninitVar // responsibility of each subclass
|
||||
VNType() = default;
|
||||
const enum en m_e;
|
||||
VNType() = delete;
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
constexpr VNType(en _e) VL_MT_SAFE : m_e{_e} {}
|
||||
explicit VNType(int _e)
|
||||
|
|
@ -2138,7 +2137,7 @@ protected:
|
|||
AstNode(VNType t, FileLine* fl);
|
||||
virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead
|
||||
virtual void cloneRelink() { cloneRelinkGen(); }
|
||||
virtual void cloneRelinkGen() = 0; // Generated by 'astgen'
|
||||
virtual void cloneRelinkGen(){}; // Overrides generated by 'astgen'
|
||||
void cloneRelinkTree();
|
||||
|
||||
// METHODS
|
||||
|
|
@ -2662,20 +2661,24 @@ public:
|
|||
// For use via privateAs or the VN_DBG_AS macro only
|
||||
template <typename T, typename E>
|
||||
static T* unsafePrivateAs(AstNode* nodep) VL_PURE {
|
||||
static_assert(!uselessCast<T, E>(), "Unnecessary VN_AS, node known to have target type.");
|
||||
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_AS, node cannot be this type.");
|
||||
static_assert(!uselessCast<T, E>(),
|
||||
"Unnecessary VN_DBG_AS, node known to have target type.");
|
||||
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_DBG_AS, node cannot be this type.");
|
||||
return reinterpret_cast<T*>(nodep);
|
||||
}
|
||||
template <typename T, typename E>
|
||||
static const T* unsafePrivateAs(const AstNode* nodep) VL_PURE {
|
||||
static_assert(!uselessCast<T, E>(), "Unnecessary VN_AS, node known to have target type.");
|
||||
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_AS, node cannot be this type.");
|
||||
static_assert(!uselessCast<T, E>(),
|
||||
"Unnecessary VN_DBG_AS, node known to have target type.");
|
||||
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_DBG_AS, node cannot be this type.");
|
||||
return reinterpret_cast<const T*>(nodep);
|
||||
}
|
||||
|
||||
// For use via the VN_AS macro only
|
||||
template <typename T, typename E>
|
||||
static T* privateAs(AstNode* nodep) VL_PURE {
|
||||
static_assert(!uselessCast<T, E>(), "Unnecessary VN_AS, node known to have target type.");
|
||||
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_AS, node cannot be this type.");
|
||||
UASSERT_OBJ(!nodep || privateTypeTest<T>(nodep), nodep,
|
||||
"AstNode is not of expected type, but instead has type '" << nodep->typeName()
|
||||
<< "'");
|
||||
|
|
@ -2683,6 +2686,8 @@ public:
|
|||
}
|
||||
template <typename T, typename E>
|
||||
static const T* privateAs(const AstNode* nodep) VL_PURE {
|
||||
static_assert(!uselessCast<T, E>(), "Unnecessary VN_AS, node known to have target type.");
|
||||
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_AS, node cannot be this type.");
|
||||
UASSERT_OBJ(!nodep || privateTypeTest<T>(nodep), nodep,
|
||||
"AstNode is not of expected type, but instead has type '" << nodep->typeName()
|
||||
<< "'");
|
||||
|
|
|
|||
|
|
@ -94,11 +94,11 @@ AstRange::AstRange(FileLine* fl, const VNumRange& range)
|
|||
rightp(new AstConst{fl, static_cast<uint32_t>(range.right())});
|
||||
}
|
||||
int AstRange::leftConst() const VL_MT_STABLE {
|
||||
AstConst* const constp = VN_CAST(leftp(), Const);
|
||||
const AstConst* const constp = VN_CAST(leftp(), Const);
|
||||
return (constp ? constp->toSInt() : 0);
|
||||
}
|
||||
int AstRange::rightConst() const VL_MT_STABLE {
|
||||
AstConst* const constp = VN_CAST(rightp(), Const);
|
||||
const AstConst* const constp = VN_CAST(rightp(), Const);
|
||||
return (constp ? constp->toSInt() : 0);
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ AstPackArrayDType::AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange*
|
|||
}
|
||||
|
||||
int AstQueueDType::boundConst() const VL_MT_STABLE {
|
||||
AstConst* const constp = VN_CAST(boundp(), Const);
|
||||
const AstConst* const constp = VN_CAST(boundp(), Const);
|
||||
return (constp ? constp->toSInt() : 0);
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ bool AstVarRef::sameNode(const AstVarRef* samep) const {
|
|||
&& (varp() && samep->varp() && varp()->name() == samep->varp()->name()));
|
||||
}
|
||||
}
|
||||
bool AstVarRef::sameNoLvalue(AstVarRef* samep) const {
|
||||
bool AstVarRef::sameNoLvalue(const AstVarRef* samep) const {
|
||||
if (varScopep()) {
|
||||
return (varScopep() == samep->varScopep());
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -792,7 +792,7 @@ public:
|
|||
|
||||
private:
|
||||
string m_name; // Name from upper typedef, if any
|
||||
const int m_uniqueNum = 0;
|
||||
const int m_uniqueNum;
|
||||
TableMap m_tableMap; // Created table for V3Width only to remove duplicates
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -656,6 +656,7 @@ public:
|
|||
childDTypep(dtp);
|
||||
dtypeFrom(dtp);
|
||||
}
|
||||
// cppcheck-suppress constParameterPointer
|
||||
AstCast(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
|
||||
: ASTGEN_SUPER_Cast(fl) {
|
||||
this->fromp(fromp);
|
||||
|
|
@ -791,14 +792,17 @@ class AstConsDynArray final : public AstNodeExpr {
|
|||
// Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
|
||||
// @astgen op1 := lhsp : Optional[AstNode]
|
||||
// @astgen op2 := rhsp : Optional[AstNode]
|
||||
const bool m_lhsIsValue = false; // LHS constructs value inside the queue, not concat
|
||||
const bool m_rhsIsValue = false; // RHS constructs value inside the queue, not concat
|
||||
const bool m_lhsIsValue; // LHS constructs value inside the queue, not concat
|
||||
const bool m_rhsIsValue; // RHS constructs value inside the queue, not concat
|
||||
public:
|
||||
explicit AstConsDynArray(FileLine* fl)
|
||||
: ASTGEN_SUPER_ConsDynArray(fl) {}
|
||||
: ASTGEN_SUPER_ConsDynArray(fl)
|
||||
, m_lhsIsValue{false}
|
||||
, m_rhsIsValue{false} {}
|
||||
explicit AstConsDynArray(FileLine* fl, bool lhsIsValue, AstNode* lhsp)
|
||||
: ASTGEN_SUPER_ConsDynArray(fl)
|
||||
, m_lhsIsValue{lhsIsValue} {
|
||||
, m_lhsIsValue{lhsIsValue}
|
||||
, m_rhsIsValue{false} {
|
||||
this->lhsp(lhsp);
|
||||
}
|
||||
explicit AstConsDynArray(FileLine* fl, bool lhsIsValue, AstNode* lhsp, bool rhsIsValue,
|
||||
|
|
@ -873,14 +877,17 @@ class AstConsQueue final : public AstNodeExpr {
|
|||
// Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
|
||||
// @astgen op1 := lhsp : Optional[AstNode]
|
||||
// @astgen op2 := rhsp : Optional[AstNode]
|
||||
const bool m_lhsIsValue = false; // LHS constructs value inside the queue, not concat
|
||||
const bool m_rhsIsValue = false; // RHS constructs value inside the queue, not concat
|
||||
const bool m_lhsIsValue; // LHS constructs value inside the queue, not concat
|
||||
const bool m_rhsIsValue; // RHS constructs value inside the queue, not concat
|
||||
public:
|
||||
explicit AstConsQueue(FileLine* fl)
|
||||
: ASTGEN_SUPER_ConsQueue(fl) {}
|
||||
: ASTGEN_SUPER_ConsQueue(fl)
|
||||
, m_lhsIsValue{false}
|
||||
, m_rhsIsValue{false} {}
|
||||
explicit AstConsQueue(FileLine* fl, bool lhsIsValue, AstNode* lhsp)
|
||||
: ASTGEN_SUPER_ConsQueue(fl)
|
||||
, m_lhsIsValue{lhsIsValue} {
|
||||
, m_lhsIsValue{lhsIsValue}
|
||||
, m_rhsIsValue{false} {
|
||||
this->lhsp(lhsp);
|
||||
}
|
||||
explicit AstConsQueue(FileLine* fl, bool lhsIsValue, AstNode* lhsp, bool rhsIsValue,
|
||||
|
|
@ -1116,6 +1123,8 @@ private:
|
|||
const int m_srcElementBits; // num bits in rhs (ex 8 if from byte-queue, 1 if from bit-queue)
|
||||
|
||||
public:
|
||||
// cppcheck-suppress constParameterPointer
|
||||
// cppcheck-suppress constParameterCallback
|
||||
AstCvtArrayToArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp, bool reverse,
|
||||
int blockSize, int dstElementBits, int srcElementBits)
|
||||
: ASTGEN_SUPER_CvtArrayToArray(fl)
|
||||
|
|
@ -1141,6 +1150,8 @@ class AstCvtArrayToPacked final : public AstNodeExpr {
|
|||
// Cast from dynamic queue data type to packed array
|
||||
// @astgen op1 := fromp : AstNodeExpr
|
||||
public:
|
||||
// cppcheck-suppress constParameterPointer
|
||||
// cppcheck-suppress constParameterCallback
|
||||
AstCvtArrayToPacked(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
|
||||
: ASTGEN_SUPER_CvtArrayToPacked(fl) {
|
||||
this->fromp(fromp);
|
||||
|
|
@ -1155,6 +1166,8 @@ class AstCvtPackedToArray final : public AstNodeExpr {
|
|||
// Cast from packed array to dynamic/unpacked queue data type
|
||||
// @astgen op1 := fromp : AstNodeExpr
|
||||
public:
|
||||
// cppcheck-suppress constParameterPointer
|
||||
// cppcheck-suppress constParameterCallback
|
||||
AstCvtPackedToArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
|
||||
: ASTGEN_SUPER_CvtPackedToArray(fl) {
|
||||
this->fromp(fromp);
|
||||
|
|
@ -1169,6 +1182,8 @@ class AstCvtUnpackedToQueue final : public AstNodeExpr {
|
|||
// Cast from unpacked array to dynamic/unpacked queue data type
|
||||
// @astgen op1 := fromp : AstNodeExpr
|
||||
public:
|
||||
// cppcheck-suppress constParameterPointer
|
||||
// cppcheck-suppress constParameterCallback
|
||||
AstCvtUnpackedToQueue(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
|
||||
: ASTGEN_SUPER_CvtUnpackedToQueue(fl) {
|
||||
this->fromp(fromp);
|
||||
|
|
@ -1604,7 +1619,6 @@ class AstLambdaArgRef final : public AstNodeExpr {
|
|||
// Lambda argument usage
|
||||
// These are not AstVarRefs because we need to be able to delete/clone lambdas during
|
||||
// optimizations and AstVar's are painful to remove.
|
||||
ASTGEN_MEMBERS_AstLambdaArgRef;
|
||||
|
||||
private:
|
||||
string m_name; // Name of variable
|
||||
|
|
@ -1615,6 +1629,7 @@ public:
|
|||
: ASTGEN_SUPER_LambdaArgRef(fl)
|
||||
, m_name{name}
|
||||
, m_index{index} {}
|
||||
ASTGEN_MEMBERS_AstLambdaArgRef;
|
||||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
string emitVerilog() override { return name(); }
|
||||
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||
|
|
@ -1812,7 +1827,7 @@ class AstRand final : public AstNodeExpr {
|
|||
// $random/$random(seed) or $urandom/$urandom(seed)
|
||||
// Return a random number, based upon width()
|
||||
// @astgen op1 := seedp : Optional[AstNode]
|
||||
const bool m_urandom = false; // $urandom vs $random
|
||||
const bool m_urandom; // $urandom vs $random
|
||||
public:
|
||||
class Reset {};
|
||||
AstRand(FileLine* fl, AstNode* seedp, bool urandom)
|
||||
|
|
@ -1994,7 +2009,7 @@ class AstScopeName final : public AstNodeExpr {
|
|||
// @astgen op1 := scopeAttrp : List[AstText]
|
||||
// @astgen op2 := scopeEntrp : List[AstText]
|
||||
bool m_dpiExport = false; // Is for dpiExport
|
||||
const bool m_forFormat = false; // Is for a format %m
|
||||
const bool m_forFormat; // Is for a format %m
|
||||
string scopeNameFormatter(AstText* scopeTextp) const;
|
||||
string scopePrettyNameFormatter(AstText* scopeTextp) const;
|
||||
|
||||
|
|
@ -4211,7 +4226,7 @@ public:
|
|||
|
||||
// === AstNodeSel ===
|
||||
class AstArraySel final : public AstNodeSel {
|
||||
void init(AstNode* fromp) {
|
||||
void init(const AstNode* fromp) {
|
||||
if (fromp && VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) {
|
||||
// Strip off array to find what array references
|
||||
dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep());
|
||||
|
|
@ -4251,7 +4266,7 @@ public:
|
|||
static AstNode* baseFromp(AstNode* nodep, bool overMembers);
|
||||
};
|
||||
class AstAssocSel final : public AstNodeSel {
|
||||
void init(AstNode* fromp) {
|
||||
void init(const AstNode* fromp) {
|
||||
if (fromp && VN_IS(fromp->dtypep()->skipRefp(), AssocArrayDType)) {
|
||||
// Strip off array to find what array references
|
||||
dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), AssocArrayDType)->subDTypep());
|
||||
|
|
@ -4285,7 +4300,7 @@ public:
|
|||
int instrCount() const override { return widthInstrs(); }
|
||||
};
|
||||
class AstWildcardSel final : public AstNodeSel {
|
||||
void init(AstNode* fromp) {
|
||||
void init(const AstNode* fromp) {
|
||||
if (fromp && VN_IS(fromp->dtypep()->skipRefp(), WildcardArrayDType)) {
|
||||
// Strip off array to find what array references
|
||||
dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), WildcardArrayDType)->subDTypep());
|
||||
|
|
@ -4976,6 +4991,8 @@ public:
|
|||
dtypeSetLogicUnsized(setwidth, minwidth, VSigning::UNSIGNED);
|
||||
}
|
||||
}
|
||||
// cppcheck-suppress constParameterPointer
|
||||
// cppcheck-suppress constParameterCallback
|
||||
AstCCast(FileLine* fl, AstNodeExpr* lhsp, AstNode* typeFromp)
|
||||
: ASTGEN_SUPER_CCast(fl, lhsp) {
|
||||
dtypeFrom(typeFromp);
|
||||
|
|
@ -5768,7 +5785,7 @@ public:
|
|||
const char* broken() const override;
|
||||
bool sameNode(const AstNode* samep) const override;
|
||||
inline bool sameNode(const AstVarRef* samep) const;
|
||||
inline bool sameNoLvalue(AstVarRef* samep) const;
|
||||
inline bool sameNoLvalue(const AstVarRef* samep) const;
|
||||
int instrCount() const override;
|
||||
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
||||
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||
|
|
|
|||
|
|
@ -784,7 +784,7 @@ class AstClassExtends final : public AstNode {
|
|||
// @astgen op1 := childDTypep : Optional[AstNodeDType]
|
||||
// @astgen op2 := classOrPkgsp : Optional[AstNode]
|
||||
// @astgen op3 := argsp : List[AstNodeExpr]
|
||||
const bool m_isImplements = false; // class implements
|
||||
const bool m_isImplements; // class implements
|
||||
bool m_parameterized = false; // has parameters in its statement
|
||||
|
||||
public:
|
||||
|
|
@ -812,8 +812,8 @@ class AstClocking final : public AstNode {
|
|||
// @astgen op2 := itemsp : List[AstClockingItem]
|
||||
// @astgen op3 := eventp : Optional[AstVar]
|
||||
std::string m_name; // Clocking block name
|
||||
const bool m_isDefault = false; // True if default clocking
|
||||
const bool m_isGlobal = false; // True if global clocking
|
||||
const bool m_isDefault; // True if default clocking
|
||||
const bool m_isGlobal; // True if global clocking
|
||||
|
||||
public:
|
||||
AstClocking(FileLine* fl, const std::string& name, AstSenItem* sensesp,
|
||||
|
|
@ -1531,7 +1531,7 @@ public:
|
|||
// Create new MODULETEMP variable under this scope
|
||||
AstVarScope* createTemp(const string& name, unsigned width);
|
||||
AstVarScope* createTemp(const string& name, AstNodeDType* dtypep);
|
||||
AstVarScope* createTempLike(const string& name, AstVarScope* vscp);
|
||||
AstVarScope* createTempLike(const string& name, const AstVarScope* vscp);
|
||||
};
|
||||
class AstSenItem final : public AstNode {
|
||||
// Parents: SENTREE
|
||||
|
|
@ -1961,7 +1961,7 @@ public:
|
|||
combineType(type);
|
||||
dtypeSetBitSized(wantwidth, VSigning::UNSIGNED);
|
||||
}
|
||||
AstVar(FileLine* fl, VVarType type, const string& name, AstVar* examplep)
|
||||
AstVar(FileLine* fl, VVarType type, const string& name, const AstVar* examplep)
|
||||
: ASTGEN_SUPER_Var(fl)
|
||||
, m_name{name}
|
||||
, m_origName{name} {
|
||||
|
|
@ -2133,7 +2133,7 @@ public:
|
|||
bool isGParam() const { return varType() == VVarType::GPARAM; }
|
||||
bool isGenVar() const { return varType() == VVarType::GENVAR; }
|
||||
bool isBitLogic() const {
|
||||
AstBasicDType* bdtypep = basicp();
|
||||
const AstBasicDType* const bdtypep = basicp();
|
||||
return bdtypep && bdtypep->isBitLogic();
|
||||
}
|
||||
bool isUsedClock() const VL_MT_SAFE { return m_usedClock; }
|
||||
|
|
@ -2486,7 +2486,7 @@ public:
|
|||
&& std::is_base_of<AstNode, T_Node>::value,
|
||||
"T_Callable 'f' must have a signature compatible with 'void(AstClass*, T_Node*)', "
|
||||
"with 'T_Node' being a subtype of 'AstNode'");
|
||||
if (AstClassExtends* const cextendsp = this->extendsp()) {
|
||||
if (const AstClassExtends* const cextendsp = this->extendsp()) {
|
||||
cextendsp->classp()->foreachMember(f);
|
||||
}
|
||||
for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
|
|
@ -2502,7 +2502,7 @@ public:
|
|||
&& std::is_base_of<AstNode, T_Node>::value,
|
||||
"Predicate 'p' must have a signature compatible with 'bool(const AstClass*, "
|
||||
"const T_Node*)', with 'T_Node' being a subtype of 'AstNode'");
|
||||
if (AstClassExtends* const cextendsp = this->extendsp()) {
|
||||
if (const AstClassExtends* const cextendsp = this->extendsp()) {
|
||||
if (cextendsp->classp()->existsMember(p)) return true;
|
||||
}
|
||||
for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
|
|
@ -2540,18 +2540,22 @@ public:
|
|||
};
|
||||
class AstModule final : public AstNodeModule {
|
||||
// A module declaration
|
||||
const bool m_isChecker = false; // Module represents a checker
|
||||
const bool m_isProgram = false; // Module represents a program
|
||||
const bool m_isChecker; // Module represents a checker
|
||||
const bool m_isProgram; // Module represents a program
|
||||
public:
|
||||
class Checker {}; // for constructor type-overload selection
|
||||
class Program {}; // for constructor type-overload selection
|
||||
AstModule(FileLine* fl, const string& name, const string& libname)
|
||||
: ASTGEN_SUPER_Module(fl, name, libname) {}
|
||||
: ASTGEN_SUPER_Module(fl, name, libname)
|
||||
, m_isChecker{false}
|
||||
, m_isProgram{false} {}
|
||||
AstModule(FileLine* fl, const string& name, const string& libname, Checker)
|
||||
: ASTGEN_SUPER_Module(fl, name, libname)
|
||||
, m_isChecker{true} {}
|
||||
, m_isChecker{true}
|
||||
, m_isProgram{false} {}
|
||||
AstModule(FileLine* fl, const string& name, const string& libname, Program)
|
||||
: ASTGEN_SUPER_Module(fl, name, libname)
|
||||
, m_isChecker{false}
|
||||
, m_isProgram{true} {}
|
||||
ASTGEN_MEMBERS_AstModule;
|
||||
string verilogKwd() const override {
|
||||
|
|
|
|||
|
|
@ -845,6 +845,7 @@ public:
|
|||
this->exprp(exprp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstStmtExpr;
|
||||
// cppcheck-suppress uselessOverride
|
||||
bool isPure() override { return exprp()->isPure(); }
|
||||
};
|
||||
class AstStop final : public AstNodeStmt {
|
||||
|
|
|
|||
|
|
@ -542,18 +542,16 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc, const string&
|
|||
string ostatic;
|
||||
if (isStatic() && namespc.empty()) ostatic = "static ";
|
||||
|
||||
const bool isRef = isDpiOpenArray()
|
||||
|| (forFunc && (isWritable() || this->isRef() || this->isConstRef()))
|
||||
|| asRef;
|
||||
asRef = asRef || isDpiOpenArray() || (forFunc && (isWritable() || isRef() || isConstRef()));
|
||||
|
||||
if (forFunc && isReadOnly() && isRef) ostatic = ostatic + "const ";
|
||||
if (forFunc && isReadOnly() && asRef) ostatic = ostatic + "const ";
|
||||
|
||||
string oname;
|
||||
if (named) {
|
||||
if (!namespc.empty()) oname += namespc + "::";
|
||||
oname += VIdProtect::protectIf(name(), protect());
|
||||
}
|
||||
return ostatic + dtypep()->cType(oname, forFunc, isRef);
|
||||
return ostatic + dtypep()->cType(oname, forFunc, asRef);
|
||||
}
|
||||
|
||||
string AstVar::vlEnumType() const {
|
||||
|
|
@ -687,7 +685,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
|
|||
if (forReturn) named = false;
|
||||
string arg;
|
||||
if (isWide() && isReadOnly()) arg += "const ";
|
||||
const bool isRef = !forReturn && (isWritable() || this->isRef() || this->isConstRef());
|
||||
const bool asRef = !forReturn && (isWritable() || this->isRef() || this->isConstRef());
|
||||
if (VN_IS(dtypeSkipRefp(), BasicDType) && !dtypeSkipRefp()->isDouble()
|
||||
&& !dtypeSkipRefp()->isString()) {
|
||||
// Backward compatible type declaration
|
||||
|
|
@ -708,12 +706,12 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
|
|||
arg += " (& " + name();
|
||||
arg += ")[" + cvtToStr(widthWords()) + "]";
|
||||
} else {
|
||||
if (isRef) arg += "&";
|
||||
if (asRef) arg += "&";
|
||||
if (named) arg += " " + name();
|
||||
}
|
||||
} else {
|
||||
// Newer internal-compatible types
|
||||
arg += dtypep()->cType((named ? name() : std::string{}), true, isRef);
|
||||
arg += dtypep()->cType((named ? name() : std::string{}), true, asRef);
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
|
@ -775,7 +773,7 @@ string AstVar::dpiTmpVarType(const string& varName) const {
|
|||
class converter final : public dpiTypesToStringConverter {
|
||||
const string m_name;
|
||||
string arraySuffix(const AstVar* varp, size_t n) const {
|
||||
if (AstUnpackArrayDType* const unpackp
|
||||
if (const AstUnpackArrayDType* const unpackp
|
||||
= VN_CAST(varp->dtypep()->skipRefp(), UnpackArrayDType)) {
|
||||
// Convert multi dimensional unpacked array to 1D array
|
||||
if (n == 0) n = 1;
|
||||
|
|
@ -849,13 +847,13 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
|||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
} else if (AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) {
|
||||
} else if (const AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) {
|
||||
if (vrefp->varp()->isSc()) {
|
||||
return vrefp->varp();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
} else if (AstArraySel* const arraySelp = VN_CAST(nodep, ArraySel)) {
|
||||
} else if (const AstArraySel* const arraySelp = VN_CAST(nodep, ArraySel)) {
|
||||
if (AstVar* const p = scVarRecurse(arraySelp->fromp())) return p;
|
||||
}
|
||||
return nullptr;
|
||||
|
|
@ -1194,7 +1192,7 @@ AstVarScope* AstScope::createTemp(const string& name, AstNodeDType* dtypep) {
|
|||
return vscp;
|
||||
}
|
||||
|
||||
AstVarScope* AstScope::createTempLike(const string& name, AstVarScope* vscp) {
|
||||
AstVarScope* AstScope::createTempLike(const string& name, const AstVarScope* vscp) {
|
||||
return createTemp(name, vscp->dtypep());
|
||||
}
|
||||
|
||||
|
|
@ -1568,7 +1566,7 @@ void AstNode::dump(std::ostream& str) const {
|
|||
} else {
|
||||
str << " @dt=" << nodeAddr(dtypep()) << "@";
|
||||
}
|
||||
if (AstNodeDType* const dtp = dtypep()) dtp->dumpSmall(str);
|
||||
if (const AstNodeDType* const dtp = dtypep()) dtp->dumpSmall(str);
|
||||
} else { // V3Broken will throw an error
|
||||
if (dtypep()) str << " %Error-dtype-exp=null,got=" << nodeAddr(dtypep());
|
||||
}
|
||||
|
|
@ -2217,10 +2215,10 @@ void AstRefDType::dump(std::ostream& str) const {
|
|||
if (!s_recursing) { // Prevent infinite dump if circular typedefs
|
||||
s_recursing = true;
|
||||
str << " -> ";
|
||||
if (const auto subp = subDTypep()) {
|
||||
if (const AstNodeDType* const subp = subDTypep()) {
|
||||
if (typedefp()) str << "typedef=" << static_cast<void*>(typedefp()) << " -> ";
|
||||
subp->dump(str);
|
||||
} else if (const auto subp = typedefp()) {
|
||||
} else if (const AstTypedef* const subp = typedefp()) {
|
||||
subp->dump(str);
|
||||
}
|
||||
s_recursing = false;
|
||||
|
|
@ -2264,7 +2262,7 @@ string AstNodeUOrStructDType::prettyDTypeName(bool full) const {
|
|||
void AstNodeDType::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
if (generic()) str << " [GENERIC]";
|
||||
if (AstNodeDType* const dtp = virtRefDTypep()) {
|
||||
if (const AstNodeDType* const dtp = virtRefDTypep()) {
|
||||
str << " refdt=" << nodeAddr(dtp);
|
||||
dtp->dumpSmall(str);
|
||||
}
|
||||
|
|
@ -2476,7 +2474,7 @@ void AstMTaskBody::dumpJson(std::ostream& str) const {
|
|||
void AstTypeTable::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
for (int i = 0; i < static_cast<int>(VBasicDTypeKwd::_ENUM_MAX); ++i) {
|
||||
if (AstBasicDType* const subnodep = m_basicps[i]) {
|
||||
if (const AstBasicDType* const subnodep = m_basicps[i]) {
|
||||
str << '\n'; // Newline from caller, so newline first
|
||||
str << "\t\t" << std::setw(8) << VBasicDTypeKwd{i}.ascii();
|
||||
str << " -> ";
|
||||
|
|
@ -2486,7 +2484,7 @@ void AstTypeTable::dump(std::ostream& str) const {
|
|||
{
|
||||
const DetailedMap& mapr = m_detailedMap;
|
||||
for (const auto& itr : mapr) {
|
||||
AstBasicDType* const dtypep = itr.second;
|
||||
const AstBasicDType* const dtypep = itr.second;
|
||||
str << '\n'; // Newline from caller, so newline first
|
||||
str << "\t\tdetailed -> ";
|
||||
dtypep->dump(str);
|
||||
|
|
@ -2591,15 +2589,21 @@ void AstNodeVarRef::dumpJson(std::ostream& str) const {
|
|||
AstNodeVarRef* AstNodeVarRef::varRefLValueRecurse(AstNode* nodep) {
|
||||
// Given a (possible) lvalue expression, recurse to find the being-set NodeVarRef, else nullptr
|
||||
if (AstNodeVarRef* const anodep = VN_CAST(nodep, NodeVarRef)) return anodep;
|
||||
if (AstNodeSel* const anodep = VN_CAST(nodep, NodeSel))
|
||||
if (const AstNodeSel* const anodep = VN_CAST(nodep, NodeSel)) {
|
||||
return varRefLValueRecurse(anodep->fromp());
|
||||
if (AstSel* const anodep = VN_CAST(nodep, Sel)) return varRefLValueRecurse(anodep->fromp());
|
||||
if (AstArraySel* const anodep = VN_CAST(nodep, ArraySel))
|
||||
}
|
||||
if (const AstSel* const anodep = VN_CAST(nodep, Sel)) {
|
||||
return varRefLValueRecurse(anodep->fromp());
|
||||
if (AstMemberSel* const anodep = VN_CAST(nodep, MemberSel))
|
||||
}
|
||||
if (const AstArraySel* const anodep = VN_CAST(nodep, ArraySel)) {
|
||||
return varRefLValueRecurse(anodep->fromp());
|
||||
if (AstStructSel* const anodep = VN_CAST(nodep, StructSel))
|
||||
}
|
||||
if (const AstMemberSel* const anodep = VN_CAST(nodep, MemberSel)) {
|
||||
return varRefLValueRecurse(anodep->fromp());
|
||||
}
|
||||
if (const AstStructSel* const anodep = VN_CAST(nodep, StructSel)) {
|
||||
return varRefLValueRecurse(anodep->fromp());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -2796,9 +2800,12 @@ AstNodeModule* AstClassOrPackageRef::classOrPackageSkipp() const {
|
|||
if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) {
|
||||
foundp = anodep->skipRefOrNullp();
|
||||
}
|
||||
if (AstTypedef* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep();
|
||||
if (AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType))
|
||||
if (const AstTypedef* const anodep = VN_CAST(foundp, Typedef)) {
|
||||
foundp = anodep->subDTypep();
|
||||
}
|
||||
if (const AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType)) {
|
||||
foundp = anodep->classp();
|
||||
}
|
||||
}
|
||||
return VN_CAST(foundp, NodeModule);
|
||||
}
|
||||
|
|
@ -3076,7 +3083,7 @@ void AstCAwait::dump(std::ostream& str) const {
|
|||
}
|
||||
void AstCAwait::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
|
||||
int AstCMethodHard::instrCount() const {
|
||||
if (AstBasicDType* const basicp = fromp()->dtypep()->basicp()) {
|
||||
if (const AstBasicDType* const basicp = fromp()->dtypep()->basicp()) {
|
||||
// TODO: add a more structured description of library methods, rather than using string
|
||||
// matching. See issue #3715.
|
||||
if (basicp->isTriggerVec() && m_name == "word") {
|
||||
|
|
@ -3165,8 +3172,8 @@ void AstCMethodHard::setPurity() {
|
|||
if (name() == "atWriteAppend" || name() == "atWriteAppendBack") {
|
||||
m_pure = false;
|
||||
// Treat atWriteAppend as pure if the argument is a loop iterator
|
||||
if (AstNodeExpr* const argp = pinsp()) {
|
||||
if (AstVarRef* const varrefp = VN_CAST(argp, VarRef)) {
|
||||
if (const AstNodeExpr* const argp = pinsp()) {
|
||||
if (const AstVarRef* const varrefp = VN_CAST(argp, VarRef)) {
|
||||
if (varrefp->varp()->isUsedLoopIdx()) m_pure = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -455,7 +455,7 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) {
|
|||
lastp->unlinkFrBack(&handle);
|
||||
if (const AstNodeArrayDType* const adtypep = VN_CAST(fromDtp, NodeArrayDType)) {
|
||||
loopp = createForeachLoopRanged(nodep, bodyPointp, varp, adtypep->declRange());
|
||||
} else if (AstBasicDType* const adtypep = VN_CAST(fromDtp, BasicDType)) {
|
||||
} else if (const AstBasicDType* const adtypep = VN_CAST(fromDtp, BasicDType)) {
|
||||
if (adtypep->isString()) {
|
||||
AstConst* const leftp = new AstConst{fl, 0};
|
||||
AstNodeExpr* const rightp = new AstLenN{fl, fromp->cloneTreePure(false)};
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class BranchVisitor final : public VNVisitorConst {
|
|||
m_likely = false;
|
||||
m_unlikely = false;
|
||||
}
|
||||
void checkUnlikely(AstNode* nodep) {
|
||||
void checkUnlikely(const AstNode* nodep) {
|
||||
if (nodep->isUnlikely()) {
|
||||
UINFO(4, " UNLIKELY: " << nodep);
|
||||
m_unlikely++;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class CUseVisitor final : public VNVisitorConst {
|
|||
std::map<std::string, std::pair<FileLine*, VUseType>> m_didUse; // What we already used
|
||||
|
||||
// METHODS
|
||||
void addNewUse(AstNode* nodep, VUseType useType, const string& name) {
|
||||
void addNewUse(const AstNode* nodep, VUseType useType, const string& name) {
|
||||
auto e = m_didUse.emplace(name, std::make_pair(nodep->fileline(), useType));
|
||||
if (e.second || ((e.first->second.second & useType) != useType)) {
|
||||
e.first->second.second = e.first->second.second | useType;
|
||||
|
|
@ -73,7 +73,8 @@ class CUseVisitor final : public VNVisitorConst {
|
|||
if (stypep && stypep->classOrPackagep()) {
|
||||
addNewUse(nodep, VUseType::INT_INCLUDE, stypep->classOrPackagep()->name());
|
||||
iterateChildrenConst(stypep);
|
||||
} else if (AstClassRefDType* const classp = VN_CAST(nodep->skipRefp(), ClassRefDType)) {
|
||||
} else if (const AstClassRefDType* const classp
|
||||
= VN_CAST(nodep->skipRefp(), ClassRefDType)) {
|
||||
addNewUse(nodep, VUseType::INT_FWD_CLASS, classp->name());
|
||||
}
|
||||
}
|
||||
|
|
@ -95,7 +96,7 @@ public:
|
|||
: m_modp{modp} {
|
||||
iterateConst(modp);
|
||||
|
||||
for (auto& used : m_didUse) {
|
||||
for (const auto& used : m_didUse) {
|
||||
AstCUse* const newp = new AstCUse{used.second.first, used.second.second, used.first};
|
||||
m_modp->addStmtsp(newp);
|
||||
UINFO(8, "Insert " << newp);
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ class CaseVisitor final : public VNVisitor {
|
|||
const uint32_t val = numval.toUInt();
|
||||
|
||||
uint32_t firstOverlap = 0;
|
||||
AstNode* overlappedCondp = nullptr;
|
||||
const AstNode* overlappedCondp = nullptr;
|
||||
bool foundHit = false;
|
||||
for (uint32_t i = 0; i < numCases; ++i) {
|
||||
if ((i & mask) == val) {
|
||||
|
|
@ -307,7 +307,7 @@ class CaseVisitor final : public VNVisitor {
|
|||
// Not done earlier, as we may now have a nullptr because it's just a ";" NOP branch
|
||||
for (uint32_t i = 0; i < numCases; ++i) {
|
||||
if (AstNode* const condp = m_valueItem[i]) {
|
||||
AstCaseItem* caseItemp = caseItemMap[condp];
|
||||
const AstCaseItem* const caseItemp = caseItemMap[condp];
|
||||
UASSERT(caseItemp, "caseItemp should exist");
|
||||
m_valueItem[i] = caseItemp->stmtsp();
|
||||
}
|
||||
|
|
@ -325,7 +325,7 @@ class CaseVisitor final : public VNVisitor {
|
|||
} else {
|
||||
// Make left and right subtrees
|
||||
// cexpr[msb:lsb] == 1
|
||||
AstNode* tree0p = replaceCaseFastRecurse(cexprp, msb - 1, upperValue | 0);
|
||||
AstNode* tree0p = replaceCaseFastRecurse(cexprp, msb - 1, upperValue);
|
||||
AstNode* tree1p = replaceCaseFastRecurse(
|
||||
cexprp, msb - 1, upperValue | (1UL << static_cast<uint32_t>(msb)));
|
||||
|
||||
|
|
@ -548,7 +548,7 @@ class CaseVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
bool neverItem(AstCase* casep, AstConst* itemp) {
|
||||
bool neverItem(const AstCase* casep, const AstConst* itemp) {
|
||||
// Xs in case or casez are impossible due to two state simulations
|
||||
if (casep->casex()) {
|
||||
} else if (casep->casez() || casep->caseInside()) {
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class CastVisitor final : public VNVisitor {
|
|||
ensureLower32Cast(castp);
|
||||
nodep->user1(1); // Now must be of known size
|
||||
}
|
||||
static int castSize(AstNode* nodep) {
|
||||
static int castSize(const AstNode* nodep) {
|
||||
if (nodep->isQuad()) {
|
||||
return VL_QUADSIZE;
|
||||
} else if (nodep->width() <= 8) {
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class CfgLiveVariables final : VNVisitorConst {
|
|||
// Check and return if variable is incompatible
|
||||
bool incompatible(Variable* varp) {
|
||||
if (!isSupportedPackedDType(varp->dtypep())) return true;
|
||||
AstVar* astVarp = nullptr;
|
||||
const AstVar* astVarp = nullptr;
|
||||
// TODO: remove the useless reinterpret_casts when C++17 'if constexpr' actually works
|
||||
if VL_CONSTEXPR_CXX17 (T_Scoped) {
|
||||
astVarp = reinterpret_cast<AstVarScope*>(varp)->varp();
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ public:
|
|||
modp->addStmtsp(nodep);
|
||||
}
|
||||
// BFS to mark public typedefs.
|
||||
std::set<AstNodeUOrStructDType*> pubStrDtypeps;
|
||||
std::set<const AstNodeUOrStructDType*> pubStrDtypeps;
|
||||
while (!m_pubStrDtypeps.empty()) {
|
||||
AstNodeUOrStructDType* const dtypep = m_pubStrDtypeps.front();
|
||||
m_pubStrDtypeps.pop();
|
||||
|
|
@ -270,7 +270,8 @@ public:
|
|||
}
|
||||
}
|
||||
for (AstTypedef* typedefp : m_typedefps) {
|
||||
AstNodeUOrStructDType* const sdtypep = VN_AS(typedefp->dtypep(), NodeUOrStructDType);
|
||||
const AstNodeUOrStructDType* const sdtypep
|
||||
= VN_AS(typedefp->dtypep(), NodeUOrStructDType);
|
||||
if (pubStrDtypeps.count(sdtypep)) typedefp->attrPublic(true);
|
||||
}
|
||||
// Clear package pointer of non-public packed struct / union type, which will never be
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class CleanVisitor final : public VNVisitor {
|
|||
// METHODS
|
||||
|
||||
// Width resetting
|
||||
int cppWidth(AstNode* nodep) {
|
||||
int cppWidth(const AstNode* nodep) {
|
||||
if (nodep->width() <= VL_IDATASIZE) {
|
||||
return VL_IDATASIZE;
|
||||
} else if (nodep->width() <= VL_QUADSIZE) {
|
||||
|
|
@ -101,7 +101,9 @@ class CleanVisitor final : public VNVisitor {
|
|||
|
||||
// Store the clean state in the userp on each node
|
||||
void setCleanState(AstNode* nodep, CleanState clean) { nodep->user1(clean); }
|
||||
CleanState getCleanState(AstNode* nodep) { return static_cast<CleanState>(nodep->user1()); }
|
||||
CleanState getCleanState(const AstNode* nodep) {
|
||||
return static_cast<CleanState>(nodep->user1());
|
||||
}
|
||||
bool isClean(AstNode* nodep) {
|
||||
const CleanState clstate = getCleanState(nodep);
|
||||
if (clstate == CS_CLEAN) return true;
|
||||
|
|
|
|||
|
|
@ -170,8 +170,8 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
|
|||
|
||||
struct BitPolarityEntry final { // Found bit polarity during iterate()
|
||||
LeafInfo m_info;
|
||||
bool m_polarity;
|
||||
int m_bit;
|
||||
bool m_polarity = false;
|
||||
int m_bit = 0;
|
||||
BitPolarityEntry(const LeafInfo& info, bool pol, int bit)
|
||||
: m_info{info}
|
||||
, m_polarity{pol}
|
||||
|
|
@ -392,7 +392,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
|
|||
|
||||
#define CONST_BITOP_SET_FAILED(reason, nodep) setFailed(true, reason, nodep, __LINE__)
|
||||
|
||||
bool setFailed(bool fail, const char* reason, AstNode* nodep, int line) {
|
||||
bool setFailed(bool fail, const char* reason, const AstNode* nodep, int line) {
|
||||
if (fail && !m_failed) {
|
||||
UINFO(9, "cannot optimize " << m_rootp << " reason:" << reason << " called from line:"
|
||||
<< line << " when checking:" << nodep);
|
||||
|
|
@ -460,7 +460,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
|
|||
}
|
||||
void visit(AstShiftR* nodep) override {
|
||||
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
|
||||
AstConst* const constp = VN_CAST(nodep->rhsp(), Const);
|
||||
const AstConst* const constp = VN_CAST(nodep->rhsp(), Const);
|
||||
CONST_BITOP_RETURN_IF(!constp, nodep->rhsp());
|
||||
m_lsb += constp->toUInt();
|
||||
incrOps(nodep, __LINE__);
|
||||
|
|
@ -484,7 +484,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
|
|||
}
|
||||
void visit(AstWordSel* nodep) override {
|
||||
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
|
||||
AstConst* const constp = VN_CAST(nodep->bitp(), Const);
|
||||
const AstConst* const constp = VN_CAST(nodep->bitp(), Const);
|
||||
CONST_BITOP_RETURN_IF(!constp, nodep->bitp());
|
||||
UASSERT_OBJ(m_leafp->wordIdx() == -1, nodep, "Unexpected nested WordSel");
|
||||
m_leafp->wordIdx(constp->toSInt());
|
||||
|
|
@ -796,7 +796,7 @@ public:
|
|||
|
||||
if (debug() >= 9) { // LCOV_EXCL_START
|
||||
cout << "- Bitop tree considered:\n";
|
||||
for (AstNodeExpr* const termp : termps) termp->dumpTree("- Reduced term: ");
|
||||
for (const AstNodeExpr* const termp : termps) termp->dumpTree("- Reduced term: ");
|
||||
for (const std::pair<AstNodeExpr*, FrozenNodeInfo>& termp : visitor.m_frozenNodes) {
|
||||
termp.first->dumpTree("- Frozen term with lsb "
|
||||
+ std::to_string(termp.second.m_lsb) + " polarity "
|
||||
|
|
@ -916,7 +916,6 @@ class ConstVisitor final : public VNVisitor {
|
|||
// AstEnum::user4 -> bool. Recursing.
|
||||
|
||||
// STATE
|
||||
static constexpr bool m_doShort = true; // Remove expressions that short circuit
|
||||
bool m_params = false; // If true, propagate parameterized and true numbers only
|
||||
bool m_required = false; // If true, must become a constant
|
||||
bool m_wremove = true; // Inside scope, no assignw removal
|
||||
|
|
@ -949,12 +948,12 @@ class ConstVisitor final : public VNVisitor {
|
|||
const V3Number& numc = VN_AS(nodep, Const)->num();
|
||||
return !numc.isNumber() ? numc : V3Number{nodep, nodep->widthMinV(), numc};
|
||||
}
|
||||
V3Number toNumC(AstNode* nodep, V3Number& numv) {
|
||||
V3Number toNumC(AstNode* nodep, const V3Number& numv) {
|
||||
// Extend V width back to C width for given node
|
||||
return !numv.isNumber() ? numv : V3Number{nodep, nodep->width(), numv};
|
||||
}
|
||||
|
||||
bool operandConst(AstNode* nodep) { return VN_IS(nodep, Const); }
|
||||
bool operandConst(const AstNode* nodep) { return VN_IS(nodep, Const); }
|
||||
bool operandAsvConst(const AstNode* nodep) {
|
||||
// BIASV(CONST, BIASV(CONST,...)) -> BIASV( BIASV_CONSTED(a,b), ...)
|
||||
const AstNodeBiComAsv* const bnodep = VN_CAST(nodep, NodeBiComAsv);
|
||||
|
|
@ -1022,8 +1021,9 @@ class ConstVisitor final : public VNVisitor {
|
|||
UASSERT_OBJ(constp && constp->isOne(), andp->lhsp(), "TRREEOPC must meet this condition");
|
||||
AstNodeExpr* const rhsp = andp->rhsp();
|
||||
AstCCast* ccastp = nullptr;
|
||||
const auto isEqOrNeq
|
||||
= [](AstNode* nodep) -> bool { return VN_IS(nodep, Eq) || VN_IS(nodep, Neq); };
|
||||
const auto isEqOrNeq = [](const AstNode* nodep) -> bool { //
|
||||
return VN_IS(nodep, Eq) || VN_IS(nodep, Neq);
|
||||
};
|
||||
if (isEqOrNeq(rhsp)) {
|
||||
ccastp = new AstCCast{andp->fileline(), rhsp->unlinkFrBack(), andp};
|
||||
} else if (AstCCast* const tmpp = VN_CAST(rhsp, CCast)) {
|
||||
|
|
@ -1352,8 +1352,8 @@ class ConstVisitor final : public VNVisitor {
|
|||
return false;
|
||||
}
|
||||
AstNodeExpr* const ap = shiftp->lhsp();
|
||||
AstConst* const bp = VN_AS(shiftp->rhsp(), Const);
|
||||
AstConst* const lp = VN_AS(nodep->lsbp(), Const);
|
||||
const AstConst* const bp = VN_AS(shiftp->rhsp(), Const);
|
||||
const AstConst* const lp = VN_AS(nodep->lsbp(), Const);
|
||||
if (bp->isWide() || bp->num().isFourState() || bp->num().isNegative() || lp->isWide()
|
||||
|| lp->num().isFourState() || lp->num().isNegative()) {
|
||||
return false;
|
||||
|
|
@ -1402,7 +1402,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
// Avoids compiler warning
|
||||
const AstExtend* const extendp = VN_CAST(nodep->rhsp(), Extend);
|
||||
if (!extendp) return false;
|
||||
AstNode* const smallerp = extendp->lhsp();
|
||||
const AstNode* const smallerp = extendp->lhsp();
|
||||
const int subsize = smallerp->width();
|
||||
const AstConst* const constp = VN_CAST(nodep->lhsp(), Const);
|
||||
if (!constp) return false;
|
||||
|
|
@ -1459,7 +1459,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
return false; // Not a transform, so NOP
|
||||
}
|
||||
|
||||
static bool operandsSame(AstNode* node1p, AstNode* node2p) {
|
||||
static bool operandsSame(const AstNode* node1p, const AstNode* node2p) {
|
||||
// For now we just detect constants & simple vars, though it could be more generic
|
||||
if (VN_IS(node1p, Const) && VN_IS(node2p, Const)) return node1p->sameGateTree(node2p);
|
||||
if (VN_IS(node1p, VarRef) && VN_IS(node2p, VarRef)) {
|
||||
|
|
@ -1469,8 +1469,8 @@ class ConstVisitor final : public VNVisitor {
|
|||
return node1p->isSame(node2p);
|
||||
}
|
||||
// Pattern created by coverage-line; avoid compiler tautological-compare warning
|
||||
if (AstAnd* const and1p = VN_CAST(node1p, And)) {
|
||||
if (AstAnd* const and2p = VN_CAST(node2p, And)) {
|
||||
if (const AstAnd* const and1p = VN_CAST(node1p, And)) {
|
||||
if (const AstAnd* const and2p = VN_CAST(node2p, And)) {
|
||||
if (VN_IS(and1p->lhsp(), Const) && VN_IS(and1p->rhsp(), NodeVarRef)
|
||||
&& VN_IS(and2p->lhsp(), Const) && VN_IS(and2p->rhsp(), NodeVarRef))
|
||||
return node1p->sameGateTree(node2p);
|
||||
|
|
@ -1535,11 +1535,11 @@ class ConstVisitor final : public VNVisitor {
|
|||
if (!lselp || !rselp) return false;
|
||||
|
||||
// a[a:b] a[b-1:c] are adjacent
|
||||
AstNode* const lfromp = lselp->fromp();
|
||||
AstNode* const rfromp = rselp->fromp();
|
||||
const AstNode* const lfromp = lselp->fromp();
|
||||
const AstNode* const rfromp = rselp->fromp();
|
||||
if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false;
|
||||
AstConst* const lstart = VN_CAST(lselp->lsbp(), Const);
|
||||
AstConst* const rstart = VN_CAST(rselp->lsbp(), Const);
|
||||
const AstConst* const lstart = VN_CAST(lselp->lsbp(), Const);
|
||||
const AstConst* const rstart = VN_CAST(rselp->lsbp(), Const);
|
||||
if (!lstart || !rstart) return false; // too complicated
|
||||
const int rend = (rstart->toSInt() + rselp->widthConst());
|
||||
// a[i:j] a[j-1:k]
|
||||
|
|
@ -2209,11 +2209,11 @@ class ConstVisitor final : public VNVisitor {
|
|||
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)) {
|
||||
if (VN_IS(dstDTypep, QueueDType) || VN_IS(dstDTypep, DynArrayDType)) {
|
||||
int srcElementBits = 0;
|
||||
if (AstNodeDType* const elemDtp = srcDTypep->subDTypep()) {
|
||||
if (const AstNodeDType* const elemDtp = srcDTypep->subDTypep()) {
|
||||
srcElementBits = elemDtp->width();
|
||||
}
|
||||
int dstElementBits = 0;
|
||||
if (AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
|
||||
if (const AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
|
||||
dstElementBits = elemDtp->width();
|
||||
}
|
||||
srcp = new AstCvtArrayToArray{
|
||||
|
|
@ -2243,7 +2243,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
AstNodeExpr* const dstp = VN_AS(streamp, StreamL)->lhsp()->unlinkFrBack();
|
||||
AstNodeDType* const dstDTypep = dstp->dtypep()->skipRefp();
|
||||
AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack();
|
||||
AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||
const AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||
const int sWidth = srcp->width();
|
||||
const int dWidth = dstp->width();
|
||||
// Connect the rhs to the stream operator and update its width
|
||||
|
|
@ -2306,7 +2306,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
} else if (m_doV && VN_IS(nodep->rhsp(), StreamL)) {
|
||||
AstStreamL* streamp = VN_AS(nodep->rhsp(), StreamL);
|
||||
AstNodeExpr* srcp = streamp->lhsp();
|
||||
AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||
const AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||
AstNodeDType* const dstDTypep = nodep->lhsp()->dtypep()->skipRefp();
|
||||
if ((VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)
|
||||
|| VN_IS(srcDTypep, UnpackArrayDType))) {
|
||||
|
|
@ -2330,11 +2330,11 @@ class ConstVisitor final : public VNVisitor {
|
|||
// streamp->rhsp()->prettyTypeName() << ")");
|
||||
// }
|
||||
int srcElementBits = 0;
|
||||
if (AstNodeDType* const elemDtp = srcDTypep->subDTypep()) {
|
||||
if (const AstNodeDType* const elemDtp = srcDTypep->subDTypep()) {
|
||||
srcElementBits = elemDtp->width();
|
||||
}
|
||||
int dstElementBits = 0;
|
||||
if (AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
|
||||
if (const AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
|
||||
dstElementBits = elemDtp->width();
|
||||
}
|
||||
streamp->unlinkFrBack();
|
||||
|
|
@ -2500,7 +2500,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
bool matchConcatRand(AstConcat* nodep) {
|
||||
// CONCAT(RAND, RAND) - created by Chisel code
|
||||
AstRand* const aRandp = VN_CAST(nodep->lhsp(), Rand);
|
||||
AstRand* const bRandp = VN_CAST(nodep->rhsp(), Rand);
|
||||
const AstRand* const bRandp = VN_CAST(nodep->rhsp(), Rand);
|
||||
if (!aRandp || !bRandp) return false;
|
||||
if (!aRandp->combinable(bRandp)) return false;
|
||||
UINFO(4, "Concat(Rand,Rand) => Rand: " << nodep);
|
||||
|
|
@ -2518,15 +2518,15 @@ class ConstVisitor final : public VNVisitor {
|
|||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
return true;
|
||||
}
|
||||
int operandConcatMove(AstConcat* nodep) {
|
||||
int operandConcatMove(const AstConcat* nodep) {
|
||||
// CONCAT under concat (See moveConcat)
|
||||
// Return value: true indicates to do it; 2 means move to LHS
|
||||
const AstConcat* const abConcp = VN_CAST(nodep->lhsp(), Concat);
|
||||
const AstConcat* const bcConcp = VN_CAST(nodep->rhsp(), Concat);
|
||||
if (!abConcp && !bcConcp) return 0;
|
||||
if (bcConcp) {
|
||||
AstNodeExpr* const ap = nodep->lhsp();
|
||||
AstNodeExpr* const bp = bcConcp->lhsp();
|
||||
const AstNodeExpr* const ap = nodep->lhsp();
|
||||
const AstNodeExpr* const bp = bcConcp->lhsp();
|
||||
// If a+b == 32,64,96 etc, then we want to have a+b together on LHS
|
||||
if (VL_BITBIT_I(ap->width() + bp->width()) == 0) return 2; // Transform 2: to abConc
|
||||
} else { // abConcp
|
||||
|
|
@ -2617,7 +2617,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
// potentially smaller lsb1p's width, but don't insert a redundant AstExtend.
|
||||
// Note that due to some sloppiness in earlier passes, lsb1p might actually be wider,
|
||||
// so extend to the wider type.
|
||||
AstNodeExpr* const widep = lsb1p->width() > lsb2p->width() ? lsb1p : lsb2p;
|
||||
const AstNodeExpr* const widep = lsb1p->width() > lsb2p->width() ? lsb1p : lsb2p;
|
||||
AstNodeExpr* const lhsp = widep->width() > lsb2p->width()
|
||||
? new AstExtend{lsb2p->fileline(), lsb2p}
|
||||
: lsb2p;
|
||||
|
|
@ -2895,7 +2895,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
// Not constant propagated (for today) because AstNodeExpr::isOpaque is set
|
||||
// Someday if lower is constant, convert to quoted "string".
|
||||
|
||||
bool onlySenItemInSenTree(AstSenItem* nodep) {
|
||||
bool onlySenItemInSenTree(const AstSenItem* nodep) {
|
||||
// Only one if it's not in a list
|
||||
return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
|
||||
}
|
||||
|
|
@ -2981,8 +2981,8 @@ class ConstVisitor final : public VNVisitor {
|
|||
if (aCallp->name() < bCallp->name()) return -1;
|
||||
if (aCallp->name() > bCallp->name()) return 1;
|
||||
if (const int c = cmp(aCallp->fromp(), bCallp->fromp())) return c;
|
||||
AstNodeExpr* aPinsp = aCallp->pinsp();
|
||||
AstNodeExpr* bPinsp = bCallp->pinsp();
|
||||
const AstNodeExpr* aPinsp = aCallp->pinsp();
|
||||
const AstNodeExpr* bPinsp = bCallp->pinsp();
|
||||
while (aPinsp && bPinsp) {
|
||||
if (const int c = cmp(aPinsp, bPinsp)) return c;
|
||||
aPinsp = VN_AS(aPinsp->nextp(), NodeExpr);
|
||||
|
|
@ -2996,8 +2996,8 @@ class ConstVisitor final : public VNVisitor {
|
|||
|
||||
public:
|
||||
bool operator()(const AstSenItem* lhsp, const AstSenItem* rhsp) const {
|
||||
AstNodeExpr* const lSensp = lhsp->sensp();
|
||||
AstNodeExpr* const rSensp = rhsp->sensp();
|
||||
const AstNodeExpr* const lSensp = lhsp->sensp();
|
||||
const AstNodeExpr* const rSensp = rhsp->sensp();
|
||||
if (lSensp && rSensp) {
|
||||
// If both terms have sensitivity expressions, recursively compare them
|
||||
if (const int c = cmp(lSensp, rSensp)) return c < 0;
|
||||
|
|
@ -3163,11 +3163,11 @@ class ConstVisitor final : public VNVisitor {
|
|||
}
|
||||
if (streamp) {
|
||||
AstNodeExpr* srcp = streamp->lhsp();
|
||||
AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||
const AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||
AstNodeDType* const dstDTypep = nodep->dtypep()->skipRefp();
|
||||
if (VN_IS(srcDTypep, QueueDType) && VN_IS(dstDTypep, QueueDType)) {
|
||||
int blockSize = 1;
|
||||
if (AstConst* const constp = VN_CAST(streamp->rhsp(), Const)) {
|
||||
if (const AstConst* const constp = VN_CAST(streamp->rhsp(), Const)) {
|
||||
blockSize = constp->toSInt();
|
||||
if (VL_UNLIKELY(blockSize <= 0)) {
|
||||
// Not reachable due to higher level checks when parsing stream
|
||||
|
|
@ -3184,11 +3184,11 @@ class ConstVisitor final : public VNVisitor {
|
|||
// streamp->rhsp()->prettyTypeName() << ")");
|
||||
// }
|
||||
int srcElementBits = 0;
|
||||
if (AstNodeDType* const elemDtp = srcDTypep->subDTypep()) {
|
||||
if (const AstNodeDType* const elemDtp = srcDTypep->subDTypep()) {
|
||||
srcElementBits = elemDtp->width();
|
||||
}
|
||||
int dstElementBits = 0;
|
||||
if (AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
|
||||
if (const AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
|
||||
dstElementBits = elemDtp->width();
|
||||
}
|
||||
streamp->unlinkFrBack();
|
||||
|
|
@ -3330,9 +3330,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
if (!prevp->fmtp() || prevp->fmtp()->nextp() || !nodep->fmtp() || nodep->fmtp()->nextp())
|
||||
return false;
|
||||
AstSFormatF* const pformatp = prevp->fmtp();
|
||||
if (!pformatp) return false;
|
||||
AstSFormatF* const nformatp = nodep->fmtp();
|
||||
if (!nformatp) return false;
|
||||
// We don't merge scopeNames as can have only one and might be different scopes (late in
|
||||
// process) Also rare for real code to print %m multiple times in same message
|
||||
if (nformatp->scopeNamep() && pformatp->scopeNamep()) return false;
|
||||
|
|
|
|||
|
|
@ -441,7 +441,7 @@ using V3ControlFileResolver = V3ControlWildcardResolver<V3ControlFile>;
|
|||
class V3ControlScopeTraceEntry final {
|
||||
public:
|
||||
const string m_scope; // Scope or regexp to match
|
||||
const bool m_on = false; // True to enable message
|
||||
const bool m_on; // True to enable message
|
||||
int m_levels = 0; // # levels, 0 = all, 1 = only this, ...
|
||||
// CONSTRUCTORS
|
||||
V3ControlScopeTraceEntry(const string& scope, bool on, int levels)
|
||||
|
|
@ -757,7 +757,8 @@ void V3Control::applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp) {
|
|||
if (ftp) ftp->apply(ftaskp);
|
||||
}
|
||||
|
||||
void V3Control::applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp) {
|
||||
void V3Control::applyVarAttr(const AstNodeModule* modulep, const AstNodeFTask* ftaskp,
|
||||
AstVar* varp) {
|
||||
V3ControlVar* vp;
|
||||
V3ControlModule* const modp
|
||||
= V3ControlResolver::s().modules().resolve(modulep->prettyOrigOrName());
|
||||
|
|
@ -797,7 +798,7 @@ bool V3Control::containsMTaskProfileData() {
|
|||
return V3ControlResolver::s().containsMTaskProfileData();
|
||||
}
|
||||
|
||||
bool V3Control::waive(FileLine* filelinep, V3ErrorCode code, const string& message) {
|
||||
bool V3Control::waive(const FileLine* filelinep, V3ErrorCode code, const string& message) {
|
||||
V3ControlFile* const filep = V3ControlResolver::s().files().resolve(filelinep->filename());
|
||||
if (!filep) return false;
|
||||
return filep->waive(code, message);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ public:
|
|||
static void applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp);
|
||||
static void applyIgnores(FileLine* filelinep);
|
||||
static void applyModule(AstNodeModule* modulep);
|
||||
static void applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp);
|
||||
static void applyVarAttr(const AstNodeModule* modulep, const AstNodeFTask* ftaskp,
|
||||
AstVar* varp);
|
||||
|
||||
static int getHierWorkers(const string& model);
|
||||
static FileLine* getHierWorkersFileLine(const string& model);
|
||||
|
|
@ -64,7 +65,7 @@ public:
|
|||
|
||||
static bool containsMTaskProfileData();
|
||||
|
||||
static bool waive(FileLine* filelinep, V3ErrorCode code, const string& message);
|
||||
static bool waive(const FileLine* filelinep, V3ErrorCode code, const string& message);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -35,30 +35,30 @@
|
|||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
class ExprCoverageEligibleVisitor final : public VNVisitor {
|
||||
class ExprCoverageEligibleVisitor final : public VNVisitorConst {
|
||||
// STATE
|
||||
bool m_eligible = true;
|
||||
|
||||
static bool elemDTypeEligible(const AstNodeDType* dtypep) {
|
||||
dtypep = dtypep->skipRefp();
|
||||
if (AstNodeDType* const dtp = dtypep->virtRefDTypep()) {
|
||||
if (const AstNodeDType* const dtp = dtypep->virtRefDTypep()) {
|
||||
if (!elemDTypeEligible(dtp)) return false;
|
||||
}
|
||||
if (AstNodeDType* const dtp = dtypep->virtRefDType2p()) {
|
||||
if (const AstNodeDType* const dtp = dtypep->virtRefDType2p()) {
|
||||
if (!elemDTypeEligible(dtp)) return false;
|
||||
}
|
||||
return !VN_IS(dtypep, ClassRefDType);
|
||||
}
|
||||
|
||||
void visit(AstNodeVarRef* nodep) override {
|
||||
AstNodeDType* dtypep = nodep->varp()->dtypep();
|
||||
const AstNodeDType* const dtypep = nodep->varp()->dtypep();
|
||||
// Class objects and references not supported for expression coverage
|
||||
// because the object may not persist until the point at which
|
||||
// coverage data is gathered
|
||||
// This could be resolved in the future by protecting against dereferrencing
|
||||
// null pointers when cloning the expression for expression coverage
|
||||
if (dtypep && elemDTypeEligible(dtypep)) {
|
||||
iterateChildren(nodep);
|
||||
iterateChildrenConst(nodep);
|
||||
} else {
|
||||
m_eligible = false;
|
||||
}
|
||||
|
|
@ -68,13 +68,13 @@ class ExprCoverageEligibleVisitor final : public VNVisitor {
|
|||
if (!nodep->isExprCoverageEligible()) {
|
||||
m_eligible = false;
|
||||
} else {
|
||||
iterateChildren(nodep);
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ExprCoverageEligibleVisitor(AstNode* nodep) { iterateChildren(nodep); }
|
||||
explicit ExprCoverageEligibleVisitor(AstNode* nodep) { iterateChildrenConst(nodep); }
|
||||
~ExprCoverageEligibleVisitor() override = default;
|
||||
|
||||
bool eligible() { return m_eligible; }
|
||||
|
|
@ -162,7 +162,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
|
||||
// METHODS
|
||||
|
||||
const char* varIgnoreToggle(AstVar* nodep) {
|
||||
const char* varIgnoreToggle(const AstVar* nodep) {
|
||||
// Return true if this shouldn't be traced
|
||||
// See also similar rule in V3TraceDecl::varIgnoreTrace
|
||||
if (!nodep->isToggleCoverable()) return "Not relevant signal type";
|
||||
|
|
@ -203,7 +203,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
}
|
||||
return incp;
|
||||
}
|
||||
string traceNameForLine(AstNode* nodep, const string& type) {
|
||||
string traceNameForLine(const AstNode* nodep, const string& type) {
|
||||
string name = "vlCoverageLineTrace_" + nodep->fileline()->filebasenameNoExt() + "__"
|
||||
+ cvtToStr(nodep->fileline()->lineno()) + "_" + type;
|
||||
if (const uint32_t suffix = m_varnames[name]++) name += "_" + cvtToStr(suffix);
|
||||
|
|
@ -438,7 +438,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
if (adtypep->packed()) {
|
||||
for (AstMemberDType* itemp = adtypep->membersp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||
AstNodeDType* const subtypep = itemp->subDTypep()->skipRefp();
|
||||
const AstNodeDType* const subtypep = itemp->subDTypep()->skipRefp();
|
||||
const int index_code = itemp->lsb();
|
||||
ToggleEnt newent{
|
||||
above.m_comment + "."s + itemp->name(),
|
||||
|
|
@ -855,7 +855,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
// not be flagged as redundant or impossible, however the results will
|
||||
// still be valid, albeit messier
|
||||
for (CoverTerm& term : l) {
|
||||
if (AstVarRef* const refp = VN_CAST(term.m_exprp, VarRef)) {
|
||||
if (const AstVarRef* const refp = VN_CAST(term.m_exprp, VarRef)) {
|
||||
varps[term.m_objective].insert(refp->varp());
|
||||
} else {
|
||||
strs[term.m_objective].insert(term.m_emitV);
|
||||
|
|
@ -865,7 +865,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
bool impossible = false;
|
||||
for (CoverTerm& term : r) {
|
||||
bool redundant = false;
|
||||
if (AstNodeVarRef* const refp = VN_CAST(term.m_exprp, NodeVarRef)) {
|
||||
if (const AstNodeVarRef* const refp = VN_CAST(term.m_exprp, NodeVarRef)) {
|
||||
if (varps[term.m_objective].find(refp->varp())
|
||||
!= varps[term.m_objective].end())
|
||||
redundant = true;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class CoverageJoinVisitor final : public VNVisitor {
|
|||
// Note uses user4
|
||||
V3DupFinder dupFinder; // Duplicate code detection
|
||||
// Hash all of the original signals we toggle cover
|
||||
for (AstCoverToggle* nodep : m_toggleps) dupFinder.insert(nodep->origp());
|
||||
for (const AstCoverToggle* const nodep : m_toggleps) dupFinder.insert(nodep->origp());
|
||||
if (dumpLevel() || debug() >= 9)
|
||||
dupFinder.dumpFile(v3Global.debugFilename("coveragejoin") + ".hash", false);
|
||||
// Find if there are any duplicates
|
||||
|
|
|
|||
|
|
@ -334,8 +334,8 @@ class DeadVisitor final : public VNVisitor {
|
|||
checkAll(typedefp);
|
||||
}
|
||||
}
|
||||
bool shouldDeleteTypedef(AstTypedef* typedefp) {
|
||||
if (auto* const structp = VN_CAST(typedefp->subDTypep(), NodeUOrStructDType)) {
|
||||
bool shouldDeleteTypedef(const AstTypedef* typedefp) {
|
||||
if (const auto* const structp = VN_CAST(typedefp->subDTypep(), NodeUOrStructDType)) {
|
||||
if (structp->user1() && !structp->packed()) return false;
|
||||
}
|
||||
return m_elimCells && !typedefp->attrPublic();
|
||||
|
|
@ -367,7 +367,7 @@ class DeadVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
}
|
||||
bool mightElimVar(AstVar* nodep) const {
|
||||
bool mightElimVar(const AstVar* nodep) const {
|
||||
if (nodep->isSigPublic()) return false; // Can't elim publics!
|
||||
if (nodep->isIO() || nodep->isClassMember() || nodep->sensIfacep()) return false;
|
||||
if (nodep->isTemp() && !nodep->isTrace()) return true;
|
||||
|
|
|
|||
|
|
@ -540,7 +540,7 @@ class DelayedVisitor final : public VNVisitor {
|
|||
}
|
||||
|
||||
// Create a unique temporary variable name
|
||||
std::string uniqueTmpName(AstScope* scopep, AstVarScope* vscp, VarScopeInfo& vscpInfo) {
|
||||
std::string uniqueTmpName(AstScope* scopep, const AstVarScope* vscp, VarScopeInfo& vscpInfo) {
|
||||
std::stringstream ss;
|
||||
ss << "__" << vscp->varp()->shortName() + "__v";
|
||||
// If the assignment is in the same scope as the variable, just
|
||||
|
|
@ -900,7 +900,7 @@ class DelayedVisitor final : public VNVisitor {
|
|||
return dtypep;
|
||||
}();
|
||||
|
||||
if (AstSel* const lSelp = VN_CAST(lhsNodep, Sel)) {
|
||||
if (const AstSel* const lSelp = VN_CAST(lhsNodep, Sel)) {
|
||||
// This is a partial assignment.
|
||||
// Need to create a mask and widen the value to element size.
|
||||
lhsNodep = lSelp->fromp();
|
||||
|
|
@ -910,7 +910,7 @@ class DelayedVisitor final : public VNVisitor {
|
|||
// Create mask value
|
||||
maskp = [&]() -> AstNodeExpr* {
|
||||
// Constant mask we can compute here
|
||||
if (AstConst* const cLsbp = VN_CAST(sLsbp, Const)) {
|
||||
if (const AstConst* const cLsbp = VN_CAST(sLsbp, Const)) {
|
||||
AstConst* const cp = new AstConst{flp, AstConst::DTyped{}, eDTypep};
|
||||
cp->num().setMask(sWidth, cLsbp->toSInt());
|
||||
return cp;
|
||||
|
|
@ -927,7 +927,7 @@ class DelayedVisitor final : public VNVisitor {
|
|||
valuep = [&]() -> AstNodeExpr* {
|
||||
// Constant value with constant select we can compute here
|
||||
if (AstConst* const cValuep = VN_CAST(valuep, Const)) {
|
||||
if (AstConst* const cLsbp = VN_CAST(sLsbp, Const)) {
|
||||
if (const AstConst* const cLsbp = VN_CAST(sLsbp, Const)) {
|
||||
AstConst* const cp = new AstConst{flp, AstConst::DTyped{}, eDTypep};
|
||||
cp->num().setAllBits0();
|
||||
cp->num().opSelInto(cValuep->num(), cLsbp->toSInt(), sWidth);
|
||||
|
|
@ -1097,7 +1097,7 @@ class DelayedVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_ignoreBlkAndNBlk);
|
||||
VL_RESTORER(m_inNonCombLogic);
|
||||
m_activep = nodep;
|
||||
AstSenTree* const senTreep = nodep->sentreep();
|
||||
const AstSenTree* const senTreep = nodep->sentreep();
|
||||
m_ignoreBlkAndNBlk = senTreep->hasStatic() || senTreep->hasInitial();
|
||||
m_inNonCombLogic = senTreep->hasClocked();
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -1160,7 +1160,7 @@ class DelayedVisitor final : public VNVisitor {
|
|||
|
||||
AstNode* newp = new AstCStmt{flp, blockp};
|
||||
if (nodep->isDelayed()) {
|
||||
AstVarRef* const vrefp = VN_AS(eventp, VarRef);
|
||||
const AstVarRef* const vrefp = VN_AS(eventp, VarRef);
|
||||
const std::string newvarname = "__Vdly__" + vrefp->varp()->shortName();
|
||||
AstVarScope* const dlyvscp
|
||||
= createTemp(flp, vrefp->varScopep()->scopep(), newvarname, 1);
|
||||
|
|
|
|||
|
|
@ -55,11 +55,11 @@ class DescopeVisitor final : public VNVisitor {
|
|||
|
||||
// METHODS
|
||||
|
||||
static bool modIsSingleton(AstNodeModule* modp) {
|
||||
static bool modIsSingleton(const AstNodeModule* modp) {
|
||||
// True iff there's exactly one instance of this module in the design (including top).
|
||||
if (modp->isTop()) return true;
|
||||
int instances = 0;
|
||||
for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
for (const AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
if (VN_IS(stmtp, Scope)) {
|
||||
if (++instances > 1) return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ struct std::hash<std::pair<const DfgVertex*, const DfgVertex*>> final {
|
|||
class VDfgType final {
|
||||
public:
|
||||
#include "V3Dfg__gen_type_enum.h" // From ./astgen
|
||||
enum en m_e;
|
||||
VDfgType() = default;
|
||||
const enum en m_e;
|
||||
VDfgType() = delete;
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
constexpr VDfgType(en _e)
|
||||
: m_e{_e} {}
|
||||
|
|
|
|||
|
|
@ -181,8 +181,8 @@ void V3DfgPasses::binToOneHot(DfgGraph& dfg, V3DfgBinToOneHotContext& ctx) {
|
|||
|
||||
// Structure to keep track of comparison details
|
||||
struct Term final {
|
||||
DfgVertex* m_vtxp; // Vertex to replace
|
||||
bool m_inv; // '!=', instead of '=='
|
||||
DfgVertex* m_vtxp = nullptr; // Vertex to replace
|
||||
bool m_inv = false; // '!=', instead of '=='
|
||||
Term() = default;
|
||||
Term(DfgVertex* vtxp, bool inv)
|
||||
: m_vtxp{vtxp}
|
||||
|
|
|
|||
|
|
@ -234,7 +234,9 @@ public:
|
|||
|
||||
uint32_t toU32() const { return static_cast<size_t>(num().toUInt()); }
|
||||
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
bool isZero() const { return num().isEqZero(); }
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
bool isOnes() const { return num().isEqAllOnes(width()); }
|
||||
|
||||
// Does this DfgConst have the given value? Note this is not easy to answer if wider than 32.
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ class V3DiagSarifImp final {
|
|||
|
||||
// METHODS
|
||||
void calculate() {
|
||||
for (auto& msgr : m_messages)
|
||||
for (const VErrorMessage& msgr : m_messages)
|
||||
if (msgr.code().isNamed()) m_codes.emplace(msgr.code());
|
||||
int i = 0;
|
||||
for (const auto& code : m_codes) m_codeIndex[code] = i++;
|
||||
for (const V3ErrorCode& code : m_codes) m_codeIndex[code] = i++;
|
||||
}
|
||||
|
||||
void putRules(V3OutJsonFile& of) const {
|
||||
for (const auto& code : m_codes) {
|
||||
for (const V3ErrorCode& code : m_codes) {
|
||||
of.begin().put("id", code.ascii()).put("helpUri", code.url()).end();
|
||||
}
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ class V3DiagSarifImp final {
|
|||
of.begin("message");
|
||||
putText(of, first_clean, first_fmt);
|
||||
of.end();
|
||||
if (auto fl = msg.fileline()) {
|
||||
if (const FileLine* const fl = msg.fileline()) {
|
||||
of.begin("locations", '[').begin();
|
||||
putLocation(of, fl);
|
||||
of.end();
|
||||
|
|
@ -175,7 +175,7 @@ public:
|
|||
.end();
|
||||
|
||||
of.begin("results", '[');
|
||||
for (auto& msgr : m_messages) putResult(of, msgr);
|
||||
for (const VErrorMessage& msgr : m_messages) putResult(of, msgr);
|
||||
of.end();
|
||||
|
||||
of.end(); // runs ]
|
||||
|
|
|
|||
|
|
@ -148,8 +148,8 @@ public:
|
|||
void emitVarAccessors(const AstVar* nodep);
|
||||
template <typename T_Callable>
|
||||
static void forModCUse(const AstNodeModule* modp, VUseType useType, T_Callable action) {
|
||||
for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) {
|
||||
if (AstCUse* const usep = VN_CAST(itemp, CUse)) {
|
||||
for (const AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) {
|
||||
if (const AstCUse* const usep = VN_CAST(itemp, CUse)) {
|
||||
if (usep->useType().containsAny(useType)) {
|
||||
if (usep->useType().containsAny(VUseType::INT_INCLUDE)) {
|
||||
action("#include \"" + prefixNameProtect(usep) + ".h\"\n");
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class EmitCConstInit VL_NOT_FINAL : public EmitCBaseVisitorConst {
|
|||
|
||||
// METHODS
|
||||
|
||||
uint32_t tabModulus(AstNodeDType* dtypep) {
|
||||
uint32_t tabModulus(const AstNodeDType* dtypep) {
|
||||
const uint32_t elemBytes = dtypep->widthTotalBytes();
|
||||
return dtypep->isString() ? 1 // String
|
||||
: elemBytes <= 2 ? 8 // CData, SData
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ class EmitCConstPool final : public EmitCConstInit {
|
|||
}
|
||||
|
||||
public:
|
||||
explicit EmitCConstPool(AstConstPool* poolp) {
|
||||
explicit EmitCConstPool(const AstConstPool* poolp) {
|
||||
emitVars(poolp);
|
||||
V3Stats::addStatSum("ConstPool, Tables emitted", m_tablesEmitted);
|
||||
V3Stats::addStatSum("ConstPool, Constants emitted", m_constsEmitted);
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ public:
|
|||
|
||||
// ACCESSORS
|
||||
void splitSizeInc(int count) { m_splitSize += count; }
|
||||
void splitSizeInc(AstNode* nodep) { splitSizeInc(nodep->nodeCount()); }
|
||||
void splitSizeInc(const AstNode* nodep) { splitSizeInc(nodep->nodeCount()); }
|
||||
void splitSizeReset() { m_splitSize = 0; }
|
||||
bool splitNeeded() const {
|
||||
return v3Global.opt.outputSplit() && m_splitSize >= v3Global.opt.outputSplit();
|
||||
|
|
@ -189,13 +189,13 @@ public:
|
|||
char fmtLetter);
|
||||
|
||||
bool emitSimpleOk(AstNodeExpr* nodep);
|
||||
void emitIQW(AstNode* nodep) {
|
||||
void emitIQW(const AstNode* nodep) {
|
||||
// See "Type letters" in verilated.h
|
||||
// Other abbrevs: "C"har, "S"hort, "F"loat, "D"ouble, stri"N"g, "R"=queue, "U"npacked
|
||||
puts(nodep->dtypep()->skipRefp()->charIQWN());
|
||||
}
|
||||
void emitRU(AstNode* nodep) {
|
||||
AstNodeDType* dtp = nodep->dtypep()->skipRefp();
|
||||
void emitRU(const AstNode* nodep) {
|
||||
const AstNodeDType* dtp = nodep->dtypep()->skipRefp();
|
||||
// See "Type letters" in verilated.h
|
||||
if (VN_IS(dtp, UnpackArrayDType))
|
||||
puts("U");
|
||||
|
|
@ -210,7 +210,7 @@ public:
|
|||
: nodep->isDouble() ? "SD"
|
||||
: (nodep->isScQuad() ? "SQ" : "SI"));
|
||||
}
|
||||
void emitDatap(AstNode* nodep) {
|
||||
void emitDatap(const AstNode* nodep) {
|
||||
// When passing to a function with va_args the compiler doesn't
|
||||
// know need a pointer so when wide, need to look inside VlWide
|
||||
if (nodep->isWide()) puts(".data()");
|
||||
|
|
@ -319,7 +319,7 @@ public:
|
|||
|
||||
// VISITORS
|
||||
using EmitCConstInit::visit;
|
||||
void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* const nodep) override {
|
||||
if (nodep->emptyBody() && !nodep->isLoose()) return;
|
||||
VL_RESTORER(m_useSelfForThis);
|
||||
VL_RESTORER(m_cfuncp);
|
||||
|
|
@ -339,7 +339,7 @@ public:
|
|||
|
||||
if (nodep->isConstructor()) {
|
||||
const AstClass* const classp = VN_CAST(nodep->scopep()->modp(), Class);
|
||||
if (nodep->isConstructor() && classp && classp->extendsp()) {
|
||||
if (classp && classp->extendsp()) {
|
||||
puts("\n : ");
|
||||
putConstructorSubinit(classp, nodep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
case AttributeType::Width: {
|
||||
if (isArrayType) {
|
||||
// For arrays, get innermost element width
|
||||
AstNodeDType* dtype = itemp->dtypep();
|
||||
const AstNodeDType* dtype = itemp->dtypep();
|
||||
while (dtype->subDTypep()) dtype = dtype->subDTypep();
|
||||
return dtype->width();
|
||||
}
|
||||
|
|
@ -461,7 +461,7 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
|
||||
AstMemberDType* itemp;
|
||||
AstMemberDType* lastItemp;
|
||||
AstMemberDType* witemp = nullptr;
|
||||
const AstMemberDType* witemp = nullptr;
|
||||
// LSB is first field in C, so loop backwards
|
||||
for (lastItemp = sdtypep->membersp(); lastItemp && lastItemp->nextp();
|
||||
lastItemp = VN_AS(lastItemp->nextp(), MemberDType)) {
|
||||
|
|
|
|||
|
|
@ -724,28 +724,28 @@ class EmitCTrace final : EmitCFunc {
|
|||
&& m_typeSplitSize >= v3Global.opt.outputSplitCTrace();
|
||||
}
|
||||
|
||||
bool emitTraceIsScBv(AstTraceInc* nodep) {
|
||||
bool emitTraceIsScBv(const AstTraceInc* nodep) {
|
||||
const AstVarRef* const varrefp = VN_CAST(nodep->declp()->valuep(), VarRef);
|
||||
if (!varrefp) return false;
|
||||
AstVar* const varp = varrefp->varp();
|
||||
const AstVar* const varp = varrefp->varp();
|
||||
return varp->isSc() && varp->isScBv();
|
||||
}
|
||||
|
||||
bool emitTraceIsScBigUint(AstTraceInc* nodep) {
|
||||
bool emitTraceIsScBigUint(const AstTraceInc* nodep) {
|
||||
const AstVarRef* const varrefp = VN_CAST(nodep->declp()->valuep(), VarRef);
|
||||
if (!varrefp) return false;
|
||||
AstVar* const varp = varrefp->varp();
|
||||
const AstVar* const varp = varrefp->varp();
|
||||
return varp->isSc() && varp->isScBigUint();
|
||||
}
|
||||
|
||||
bool emitTraceIsScUint(AstTraceInc* nodep) {
|
||||
bool emitTraceIsScUint(const AstTraceInc* nodep) {
|
||||
const AstVarRef* const varrefp = VN_CAST(nodep->declp()->valuep(), VarRef);
|
||||
if (!varrefp) return false;
|
||||
AstVar* const varp = varrefp->varp();
|
||||
const AstVar* const varp = varrefp->varp();
|
||||
return varp->isSc() && (varp->isScUint() || varp->isScUintBool());
|
||||
}
|
||||
|
||||
void emitTraceInitOne(AstTraceDecl* nodep, int enumNum) {
|
||||
void emitTraceInitOne(const AstTraceDecl* nodep, int enumNum) {
|
||||
if (nodep->dtypep()->basicp()->isDouble()) {
|
||||
puts("tracep->declDouble(");
|
||||
} else if (nodep->isWide()) {
|
||||
|
|
@ -906,7 +906,7 @@ class EmitCTrace final : EmitCFunc {
|
|||
|
||||
void emitTraceValue(AstTraceInc* nodep, int arrayindex) {
|
||||
if (AstVarRef* const varrefp = VN_CAST(nodep->valuep(), VarRef)) {
|
||||
AstVar* const varp = varrefp->varp();
|
||||
const AstVar* const varp = varrefp->varp();
|
||||
if (varp->isEvent()) puts("&");
|
||||
puts("(");
|
||||
if (emitTraceIsScBigUint(nodep)) {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class CMakeEmitter final {
|
|||
template <typename T_List>
|
||||
static string cmake_list(const T_List& strs) {
|
||||
string s;
|
||||
for (auto& itr : strs) {
|
||||
for (const std::string& itr : strs) {
|
||||
if (!s.empty()) s += ' ';
|
||||
s += '"';
|
||||
s += V3OutFormatter::quoteNameControls(itr);
|
||||
|
|
@ -49,7 +49,7 @@ class CMakeEmitter final {
|
|||
}
|
||||
static string cmake_list(const VFileLibList& strs) {
|
||||
string s;
|
||||
for (auto& itr : strs) {
|
||||
for (const VFileLibName& itr : strs) {
|
||||
if (!s.empty()) s += ' ';
|
||||
s += '"';
|
||||
s += V3OutFormatter::quoteNameControls(itr.filename());
|
||||
|
|
@ -191,14 +191,16 @@ class CMakeEmitter final {
|
|||
*of << "target_link_libraries(${TOP_TARGET_NAME} PRIVATE " << prefix << ")\n";
|
||||
if (!children.empty()) {
|
||||
*of << "target_link_libraries(" << prefix << " INTERFACE";
|
||||
for (const auto& childr : children) *of << " " << (childr)->hierPrefix();
|
||||
for (const V3HierBlock* const childp : children) {
|
||||
*of << " " << childp->hierPrefix();
|
||||
}
|
||||
*of << ")\n";
|
||||
}
|
||||
*of << "verilate(" << prefix << " PREFIX " << prefix << " TOP_MODULE "
|
||||
<< hblockp->modp()->name() << " DIRECTORY "
|
||||
<< v3Global.opt.makeDir() + "/" + prefix << " SOURCES ";
|
||||
for (const auto& childr : children) {
|
||||
*of << " " << v3Global.opt.makeDir() + "/" + childr->hierWrapperFilename(true);
|
||||
for (const V3HierBlock* const childp : children) {
|
||||
*of << " " << v3Global.opt.makeDir() + "/" + childp->hierWrapperFilename(true);
|
||||
}
|
||||
*of << " ";
|
||||
const string vFile = hblockp->vFileIfNecessary();
|
||||
|
|
|
|||
|
|
@ -152,11 +152,11 @@ private:
|
|||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
// Potentially very slow, intended for debugging
|
||||
string prettyNumber(const V3Number* nump, AstNodeDType* dtypep) {
|
||||
if (AstRefDType* const refdtypep = VN_CAST(dtypep, RefDType)) { //
|
||||
string prettyNumber(const V3Number* nump, const AstNodeDType* dtypep) {
|
||||
if (const AstRefDType* const refdtypep = VN_CAST(dtypep, RefDType)) { //
|
||||
dtypep = refdtypep->skipRefp();
|
||||
}
|
||||
if (AstNodeUOrStructDType* const stp = VN_CAST(dtypep, NodeUOrStructDType)) {
|
||||
if (const AstNodeUOrStructDType* const stp = VN_CAST(dtypep, NodeUOrStructDType)) {
|
||||
if (stp->packed()) {
|
||||
std::ostringstream out;
|
||||
out << "'{";
|
||||
|
|
@ -218,13 +218,13 @@ public:
|
|||
m_whyNotOptimizable = why;
|
||||
std::ostringstream stack;
|
||||
for (const auto& callstack : vlstd::reverse_view(m_callStack)) {
|
||||
AstFuncRef* const funcp = callstack->m_funcp;
|
||||
const AstFuncRef* const funcp = callstack->m_funcp;
|
||||
stack << "\n " << funcp->fileline() << "... Called from '"
|
||||
<< funcp->prettyName() << "()' with parameters:";
|
||||
V3TaskConnects* tconnects = callstack->m_tconnects;
|
||||
for (V3TaskConnects::iterator conIt = tconnects->begin();
|
||||
conIt != tconnects->end(); ++conIt) {
|
||||
AstVar* const portp = conIt->first;
|
||||
const AstVar* const portp = conIt->first;
|
||||
AstNodeExpr* const pinp = conIt->second->exprp();
|
||||
AstNodeDType* const dtypep = pinp->dtypep();
|
||||
if (AstConst* const valp = fetchConstNull(pinp)) {
|
||||
|
|
@ -400,7 +400,7 @@ private:
|
|||
|
||||
// True if current node might be jumped over - all visitors must call this up front
|
||||
bool jumpingOver() const { return m_jumpp; }
|
||||
void assignOutValue(AstNodeAssign* nodep, AstNode* vscp, const AstNodeExpr* valuep) {
|
||||
void assignOutValue(const AstNodeAssign* nodep, AstNode* vscp, const AstNodeExpr* valuep) {
|
||||
if (VN_IS(nodep, AssignDly)) {
|
||||
// Don't do setValue, as value isn't yet visible to following statements
|
||||
newOutValue(vscp, valuep);
|
||||
|
|
@ -458,7 +458,7 @@ private:
|
|||
m_varAux(vscp).usage |= VU_RV;
|
||||
const bool varIsConst = (nodep->varp()->isConst() || nodep->varp()->isParam())
|
||||
&& nodep->varp()->valuep();
|
||||
AstNodeExpr* const valuep
|
||||
const AstNodeExpr* const valuep
|
||||
= varIsConst ? fetchValueNull(nodep->varp()->valuep()) : nullptr;
|
||||
// Propagate PARAM constants for constant function analysis
|
||||
if (varIsConst && valuep) {
|
||||
|
|
@ -800,9 +800,7 @@ private:
|
|||
handleAssignArray(nodep, selp, valueFromp);
|
||||
} else if (AstConcat* const selp = VN_CAST(lhsp, Concat)) {
|
||||
checkNodeInfo(selp);
|
||||
AstBasicDType* const rhsBasicp
|
||||
= VN_CAST(selp->rhsp()->dtypep()->skipRefp(), BasicDType);
|
||||
if (!rhsBasicp) {
|
||||
if (!VN_IS(selp->rhsp()->dtypep()->skipRefp(), BasicDType)) {
|
||||
clearOptimizable(lhsp, "Assign LHS concat of non-basic type");
|
||||
return;
|
||||
}
|
||||
|
|
@ -879,7 +877,7 @@ private:
|
|||
checkNodeInfo(nodep);
|
||||
iterateChildrenConst(nodep);
|
||||
if (AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) {
|
||||
AstConst* const indexp = fetchConst(nodep->bitp());
|
||||
const AstConst* const indexp = fetchConst(nodep->bitp());
|
||||
const uint32_t offset = indexp->num().toUInt();
|
||||
AstNodeExpr* const itemp = initp->getIndexDefaultedValuep(offset);
|
||||
if (!itemp) {
|
||||
|
|
@ -904,7 +902,7 @@ private:
|
|||
iterateChildrenConst(nodep);
|
||||
if (m_checkOnly || !optimizable()) return;
|
||||
// Fetch the base constant array
|
||||
if (AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) {
|
||||
if (const AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) {
|
||||
const VNumRange& sliceRange = nodep->declRange();
|
||||
const uint32_t sliceElements = sliceRange.elements();
|
||||
const int sliceLo = sliceRange.lo();
|
||||
|
|
@ -962,7 +960,7 @@ private:
|
|||
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), CaseItem)) {
|
||||
if (hit) break;
|
||||
if (!hit && itemp->isDefault()) {
|
||||
if (itemp->isDefault()) {
|
||||
iterateAndNextConstNull(itemp->stmtsp());
|
||||
hit = true;
|
||||
}
|
||||
|
|
@ -1250,7 +1248,7 @@ private:
|
|||
checkNodeInfo(nodep, /*display:*/ true);
|
||||
iterateChildrenConst(nodep);
|
||||
if (m_params) {
|
||||
AstConst* const textp = fetchConst(nodep->fmtp());
|
||||
const AstConst* const textp = fetchConst(nodep->fmtp());
|
||||
switch (nodep->displayType()) {
|
||||
case VDisplayType::DT_DISPLAY: // FALLTHRU
|
||||
case VDisplayType::DT_INFO: v3warn(USERINFO, textp->name()); break;
|
||||
|
|
|
|||
39
src/astgen
39
src/astgen
|
|
@ -938,10 +938,11 @@ def write_ast_impl(filename):
|
|||
emitBlock(" BROKEN_RTN(!m_{name});\n" +
|
||||
" BROKEN_RTN(!m_{name}->brokeExists());\n",
|
||||
name=ptr['name'])
|
||||
if ptr['legals'] != '':
|
||||
legals = ptr['legals'].split('|')
|
||||
if legals and legals != ["Node"]:
|
||||
emitBlock(" BROKEN_RTN(m_{name} && !(", name=ptr['name'])
|
||||
eor = ""
|
||||
for legal in ptr['legals'].split('|'):
|
||||
for legal in legals:
|
||||
# We use privateTypeTest, as VN_IS would assert that we know
|
||||
# the type is correct, but we want to check regardless,
|
||||
# to find errors after raw node edits/replacements
|
||||
|
|
@ -956,10 +957,11 @@ def write_ast_impl(filename):
|
|||
if op is None:
|
||||
continue
|
||||
name, _, _, legals = op
|
||||
if legals != '':
|
||||
legals = legals.split('|')
|
||||
if legals and legals != ["Node"]:
|
||||
emitBlock(" BROKEN_RTN({name}() && !(", name=name)
|
||||
eor = ""
|
||||
for legal in legals.split('|'):
|
||||
for legal in legals:
|
||||
emitBlock("{eor}privateTypeTest<Ast{legal}>({name}())",
|
||||
eor=eor,
|
||||
name=name,
|
||||
|
|
@ -978,12 +980,13 @@ def write_ast_impl(filename):
|
|||
if op is None:
|
||||
continue
|
||||
name, _, _, legals = op
|
||||
if legals != '':
|
||||
legals = legals.split('|')
|
||||
if legals and legals != ["Node"]:
|
||||
# 'this' is a parent, where oldp replacing newp as op1p, must follow op1p's rules
|
||||
# Could also be on a list, we don't check for speed reasons and as V3Broken doesn't
|
||||
emitBlock(" if (oldp == op{i}p() && !(", i=i)
|
||||
eor = ""
|
||||
for legal in legals.split('|'):
|
||||
for legal in legals:
|
||||
emitBlock("{eor}privateTypeTest<Ast{legal}>(newp)",
|
||||
eor=eor,
|
||||
name=name,
|
||||
|
|
@ -994,16 +997,17 @@ def write_ast_impl(filename):
|
|||
emitBlock(" return false;\n")
|
||||
emitBlock("}}\n")
|
||||
|
||||
emitBlock("void Ast{t}::cloneRelinkGen() {{\n", t=node.name)
|
||||
if node.superClass.name != 'Node':
|
||||
emitBlock(" Ast{base}::cloneRelinkGen();\n", base=node.superClass.name)
|
||||
for ptr in node.ptrs:
|
||||
emitBlock(
|
||||
" if (m_{name} && m_{name}->clonep()) m_{name} = m_{name}->clonep();\n",
|
||||
name=ptr['name'],
|
||||
kind=ptr['kind'])
|
||||
if node.ptrs:
|
||||
emitBlock("void Ast{t}::cloneRelinkGen() {{\n", t=node.name)
|
||||
if node.superClass.name != 'Node':
|
||||
emitBlock(" Ast{base}::cloneRelinkGen();\n", base=node.superClass.name)
|
||||
for ptr in node.ptrs:
|
||||
emitBlock(
|
||||
" if (m_{name} && m_{name}->clonep()) m_{name} = m_{name}->clonep();\n",
|
||||
name=ptr['name'],
|
||||
kind=ptr['kind'])
|
||||
|
||||
emitBlock("}}\n")
|
||||
emitBlock("}}\n")
|
||||
|
||||
emitBlock("void Ast{t}::dumpJsonGen(std::ostream& str) const {{\n", t=node.name)
|
||||
if node.superClass.name != 'Node':
|
||||
|
|
@ -1067,11 +1071,14 @@ def write_ast_macros(filename):
|
|||
Ast{t}* addNext(Ast{t}* nodep) {{ return static_cast<Ast{t}*>(AstNode::addNext(this, nodep)); }}
|
||||
const char* brokenGen() const override;
|
||||
bool wouldBreakGen(const AstNode* const oldp, const AstNode* const newp) const override;
|
||||
void cloneRelinkGen() override;
|
||||
void dumpTreeJsonOpGen(std::ostream& str, const string& indent) const override;
|
||||
void dumpJsonGen(std::ostream& str) const;
|
||||
''',
|
||||
t=node.name)
|
||||
if node.ptrs:
|
||||
emitBlock('''\
|
||||
void cloneRelinkGen() override;
|
||||
''')
|
||||
|
||||
if node.isLeaf:
|
||||
emitBlock('''\
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2003-2025 by Wilson Snyder. This program is free software; you
|
||||
// can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
cstyleCast
|
||||
ctunullpointer
|
||||
derefInvalidIteratorRedundantCheck
|
||||
nullPointer
|
||||
nullPointerRedundantCheck
|
||||
templateRecursion
|
||||
unusedFunction
|
||||
unusedScopedObject
|
||||
useInitializationList
|
||||
useStlAlgorithm
|
||||
|
||||
// Seems useless
|
||||
missingIncludeSystem
|
||||
// Tedious
|
||||
unmatchedSuppression
|
||||
// Not our code
|
||||
*:include/gtkwave/*
|
||||
*:include/vltstd/*
|
||||
// We intentionally redefine AstNode methods to improve type safety
|
||||
duplInheritedMember:src/V3AstNode*.h
|
||||
duplInheritedMember:src/obj_*/V3Ast__gen_impl.h
|
||||
// We intentionally redefine DfgVertex methods to match Ast
|
||||
duplInheritedMember:src/obj_*/V3Dfg__gen_auto_classes.h
|
||||
// TODO: fix - maybe?
|
||||
duplInheritedMember:src/V3File*.h
|
||||
// They are used after astgen expansion
|
||||
unusedPrivateFunction:src/V3Const.cpp
|
||||
|
|
@ -1,196 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# pylint: disable=C0103,C0114,C0115,C0116,C0209,R0911,R0912,R0915,W0621
|
||||
######################################################################
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
SuppressMap = {
|
||||
# New cpp check error Can suppress with old error
|
||||
'nullPointerRedundantCheck': 'nullPointer'
|
||||
}
|
||||
|
||||
######################################################################
|
||||
|
||||
|
||||
def process(cppcheck_args):
|
||||
cmd = " ".join(cppcheck_args) + " 2>&1"
|
||||
if Args.debug:
|
||||
print("\t" + cmd)
|
||||
fh = os.popen(cmd)
|
||||
errs = False
|
||||
last_error = ""
|
||||
for line in fh:
|
||||
line = line.rstrip()
|
||||
if Args.debug:
|
||||
print(">>>" + line)
|
||||
line = re.sub(r'^\s+', '', line)
|
||||
# Sometimes tacked at end-of-line
|
||||
line = re.sub(r'Checking usage of global functions\.+', '', line)
|
||||
line = re.sub(r' file0="[^"]+"', r'', line)
|
||||
|
||||
if re.search(r'^<\?xml version', line):
|
||||
continue
|
||||
if re.search(r'^<cppcheck', line):
|
||||
continue
|
||||
if re.search(r'^<errors', line):
|
||||
continue
|
||||
if re.search(r'^</error>', line):
|
||||
continue
|
||||
if re.search(r'^</errors>', line):
|
||||
continue
|
||||
if re.search(r'^<results', line):
|
||||
continue
|
||||
if re.search(r'^</results>', line):
|
||||
continue
|
||||
if re.search(r'^<symbol>', line):
|
||||
continue
|
||||
# An earlier id line is more specific
|
||||
if re.search(r'Cppcheck cannot find all the include files', line):
|
||||
continue
|
||||
if re.search(r'^Checking ', line):
|
||||
continue
|
||||
if re.search(r'^make.*Entering directory ', line):
|
||||
continue
|
||||
if re.search(r'^make.*Leaving directory ', line):
|
||||
continue
|
||||
if re.search(r'^\s+$', line):
|
||||
continue
|
||||
|
||||
# Output
|
||||
if re.search(r'^cppcheck --', line):
|
||||
if Args.debug:
|
||||
print(line)
|
||||
continue
|
||||
if re.search(r'^\d+/\d+ files checked', line):
|
||||
print(line)
|
||||
continue
|
||||
|
||||
suppress = False
|
||||
# --xml-format=2
|
||||
if re.search(r'<error id', line):
|
||||
last_error = line
|
||||
continue
|
||||
|
||||
match = re.search(r'<location.* file="([^"]+)"\s+line="(\d+)"', line)
|
||||
if match:
|
||||
file = match.group(1)
|
||||
linenum = int(match.group(2))
|
||||
match = re.search(r' id="([^"]+)"', last_error)
|
||||
eid = match.group(1) if match else '?'
|
||||
if _suppress(file, linenum, eid):
|
||||
suppress = True
|
||||
if file == "*":
|
||||
suppress = True
|
||||
if not suppress:
|
||||
print("%s:%s: %s" % (file, linenum, last_error))
|
||||
suppress = True
|
||||
|
||||
if not suppress:
|
||||
eline = "%Error: cppcheck: " + line
|
||||
print(eline)
|
||||
errs = True
|
||||
|
||||
if errs:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
######################################################################
|
||||
|
||||
|
||||
def _suppress(filename, linenum, eid):
|
||||
if Args.debug:
|
||||
print("-Suppression search %s %s %s" % (filename, linenum, eid))
|
||||
|
||||
if filename == "*":
|
||||
return False
|
||||
|
||||
# Cleanup for e.g. ../V3AstNode*.h
|
||||
filename = re.sub(r'^\.\./(.*)', r'src/\1', filename)
|
||||
|
||||
# Specific suppressions
|
||||
if eid == 'asctimeCalled' and re.search(r'gtkwave/', filename):
|
||||
return True
|
||||
if eid == 'constParameter' and re.search(r'gtkwave/', filename):
|
||||
return True
|
||||
if eid == 'ctuOneDefinitionRuleViolation' and re.search(r'vltstd/', filename):
|
||||
return True
|
||||
if eid == 'duplicateConditionalAssign' and re.search(r'gtkwave/', filename):
|
||||
return True
|
||||
if eid == 'knownConditionTrueFalse' and re.search(r'gtkwave/', filename):
|
||||
return True
|
||||
if eid == 'missingInclude' and re.search(r'systemc.h', filename):
|
||||
return True
|
||||
if eid == 'missingInclude' and re.search(r'svdpi.h', filename):
|
||||
return True
|
||||
if eid == 'shiftNegativeLHS' and re.search(r'gtkwave/', filename):
|
||||
return True
|
||||
if eid == 'shiftTooManyBits' and re.search(r'gtkwave/', filename):
|
||||
return True
|
||||
if eid == 'shiftTooManyBitsSigned' and re.search(r'gtkwave/', filename):
|
||||
return True
|
||||
if eid == 'nullPointerArithmetic' and re.search(r'gtkwave/', filename):
|
||||
return True
|
||||
if eid == 'unmatchedSuppression':
|
||||
return True
|
||||
if eid == 'unusedFunction' and re.search(r'verilated_dpi.cpp', filename):
|
||||
return True
|
||||
if eid == 'unusedFunction' and re.search(r'verilated_vpi.cpp', filename):
|
||||
return True
|
||||
if eid == 'unreachableCode' and re.search(r'V3ParseBison.c', filename):
|
||||
return True
|
||||
if eid == 'unreadVariable' and re.search(r'gtkwave/', filename):
|
||||
return True
|
||||
if eid == 'uselessAssignmentPtrArg' and re.search(r'gtkwave/', filename):
|
||||
return True
|
||||
if eid == 'variableScope' and re.search(r'fstapi.c', filename):
|
||||
return True
|
||||
|
||||
if not os.path.exists(filename):
|
||||
print("%Warning: " + filename + " does not exist, ignored", file=sys.stderr)
|
||||
return False
|
||||
|
||||
with open(filename, "r", encoding="utf8") as fh:
|
||||
lineno = 0
|
||||
for line in fh:
|
||||
lineno += 1
|
||||
if (lineno + 1) == linenum:
|
||||
match = re.search(r'(cppcheck|cppcheck-has-bug|cppverilator)-suppress((\s+\S+)+)',
|
||||
line)
|
||||
if match:
|
||||
for supid in match.group(2).split():
|
||||
if (supid == eid or (eid in SuppressMap and supid == SuppressMap[eid])):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
#######################################################################
|
||||
#######################################################################
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
allow_abbrev=False,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description="""cppcheck_filtered passes all arguments to cppcheck, then
|
||||
filters out unnecessary warnings related to Verilator. Run as:
|
||||
|
||||
cd $VERILATOR_ROOT
|
||||
make -k cppcheck""",
|
||||
epilog="""Copyright 2014-2025 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""")
|
||||
|
||||
parser.add_argument('--debug', action='store_true', help='enable debug')
|
||||
|
||||
Args, cppcheck_args = parser.parse_known_args()
|
||||
|
||||
process(cppcheck_args)
|
||||
|
||||
######################################################################
|
||||
# Local Variables:
|
||||
# compile-command: "cd .. ; src/cppcheck_filtered cppcheck --xml --enable=all src/V3Width.cpp"
|
||||
# End:
|
||||
Loading…
Reference in New Issue