mirror of
https://github.com/verilator/verilator.git
synced 2025-04-30 04:26:55 +00:00
Internals: Misc refectoring for assoc/queues.
This commit is contained in:
parent
3d6e8e9eb0
commit
38e586fabe
@ -226,48 +226,56 @@ string AstVar::verilogKwd() const {
|
||||
}
|
||||
}
|
||||
|
||||
class AstVar::VlArgTypeRecurseInfo {
|
||||
class AstVar::VlArgTypeRecursed {
|
||||
public:
|
||||
bool m_named;
|
||||
bool m_forFunc;
|
||||
bool m_mayParen;
|
||||
string m_namespc;
|
||||
string paren(const string& s) {
|
||||
if (m_mayParen) { m_mayParen = false; return " ("+s+")"; }
|
||||
else return s;
|
||||
string m_oref; // To output, reference part before name, "&"
|
||||
string m_osuffix; // To output, suffixed after name, "[3]"
|
||||
string m_oprefix; // To output, prefixed before name, "Foo_t"
|
||||
void clear() {
|
||||
m_oref.clear();
|
||||
m_osuffix.clear();
|
||||
m_oprefix.clear();
|
||||
}
|
||||
string refParen(const string& name) {
|
||||
return m_oref.empty() ? name : "("+m_oref+" "+name+")";
|
||||
}
|
||||
};
|
||||
|
||||
string AstVar::vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc) const {
|
||||
UASSERT_OBJ(!forReturn, this,
|
||||
"Internal data is never passed as return, but as first argument");
|
||||
VlArgTypeRecurseInfo info;
|
||||
info.m_named = named;
|
||||
info.m_forFunc = forFunc;
|
||||
info.m_mayParen = false;
|
||||
info.m_namespc = namespc;
|
||||
|
||||
string ostatic;
|
||||
if (isStatic() && info.m_namespc.empty()) ostatic = "static ";
|
||||
return ostatic + vlArgTypeRecurse(dtypep(), &info, "");
|
||||
if (isStatic() && namespc.empty()) ostatic = "static ";
|
||||
|
||||
VlArgTypeRecursed info = vlArgTypeRecurse(forFunc, dtypep());
|
||||
|
||||
string oname;
|
||||
if (named) {
|
||||
oname += " ";
|
||||
if (!namespc.empty()) oname += namespc+"::";
|
||||
oname += VIdProtect::protectIf(name(), protect());
|
||||
}
|
||||
return ostatic + info.m_oprefix + info.refParen(oname) + info.m_osuffix;
|
||||
}
|
||||
|
||||
string AstVar::vlArgTypeRecurse(AstNodeDType* dtypep, VlArgTypeRecurseInfo* infop,
|
||||
const string& inarray) const {
|
||||
AstVar::VlArgTypeRecursed AstVar::vlArgTypeRecurse(bool forFunc,
|
||||
const AstNodeDType* dtypep) const {
|
||||
dtypep = dtypep->skipRefp();
|
||||
if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
|
||||
string oarray = "["+cvtToStr(adtypep->declRange().elements())+"]";
|
||||
return vlArgTypeRecurse(adtypep->subDTypep(), infop, inarray+oarray);
|
||||
} else if (AstBasicDType* bdtypep = basicp()) {
|
||||
if (const AstUnpackArrayDType* adtypep = VN_CAST_CONST(dtypep, UnpackArrayDType)) {
|
||||
VlArgTypeRecursed info = vlArgTypeRecurse(forFunc, adtypep->subDTypep());
|
||||
info.m_osuffix = "[" + cvtToStr(adtypep->declRange().elements()) + "]" + info.m_osuffix;
|
||||
return info;
|
||||
} else if (const AstBasicDType* bdtypep = dtypep->basicp()) {
|
||||
string otype;
|
||||
string oarray = inarray;
|
||||
string oarray;
|
||||
bool strtype = bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::STRING;
|
||||
string bitvec;
|
||||
if (bdtypep && !bdtypep->isOpaque() && !v3Global.opt.protectIds()) {
|
||||
bitvec = ("/*"+cvtToStr(bdtypep->lsb()+bdtypep->width()-1)
|
||||
+":"+cvtToStr(bdtypep->lsb())+"*/");
|
||||
// We don't print msb()/lsb() as multidim packed would require recursion,
|
||||
// and may confuse users as C++ data is stored always with bit 0 used
|
||||
bitvec += "/*"+cvtToStr(dtypep->width()-1)+":0*/";
|
||||
}
|
||||
if ((infop->m_forFunc && isReadOnly())
|
||||
if ((forFunc && isReadOnly())
|
||||
|| bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR
|
||||
|| bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) otype += "const ";
|
||||
if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR) {
|
||||
@ -280,35 +288,35 @@ string AstVar::vlArgTypeRecurse(AstNodeDType* dtypep, VlArgTypeRecurseInfo* info
|
||||
otype += "float";
|
||||
} else if (strtype) {
|
||||
otype += "std::string";
|
||||
} else if (widthMin() <= 8) {
|
||||
} else if (dtypep->widthMin() <= 8) { // Handle unpacked arrays; not bdtypep->width
|
||||
otype += "CData"+bitvec;
|
||||
} else if (widthMin() <= 16) {
|
||||
} else if (dtypep->widthMin() <= 16) {
|
||||
otype += "SData"+bitvec;
|
||||
} else if (widthMin() <= VL_WORDSIZE) {
|
||||
} else if (dtypep->widthMin() <= VL_WORDSIZE) {
|
||||
otype += "IData"+bitvec;
|
||||
} else if (isQuad()) {
|
||||
} else if (dtypep->isQuad()) {
|
||||
otype += "QData"+bitvec;
|
||||
} else if (isWide()) {
|
||||
} else if (dtypep->isWide()) {
|
||||
otype += "WData"+bitvec; // []'s added later
|
||||
oarray += "["+cvtToStr(widthWords())+"]";
|
||||
oarray += "["+cvtToStr(dtypep->widthWords())+"]";
|
||||
}
|
||||
|
||||
string oname;
|
||||
string oref;
|
||||
if (isDpiOpenArray()
|
||||
|| (infop->m_forFunc && (isWritable()
|
||||
|| (forFunc && (isWritable()
|
||||
|| direction() == VDirection::REF
|
||||
|| direction() == VDirection::CONSTREF
|
||||
|| (strtype && isNonOutput())))) {
|
||||
oname += "&";
|
||||
infop->m_mayParen = true;
|
||||
oref = "&";
|
||||
}
|
||||
if (infop->m_named) {
|
||||
oname += " ";
|
||||
if (!infop->m_namespc.empty()) oname += infop->m_namespc+"::";
|
||||
oname += VIdProtect::protectIf(name(), protect());
|
||||
}
|
||||
if (!oarray.empty()) oname = infop->paren(oname);
|
||||
return otype+oname+oarray;
|
||||
|
||||
VlArgTypeRecursed info;
|
||||
info.m_oprefix = otype;
|
||||
info.m_osuffix = oarray;
|
||||
info.m_oref = oref;
|
||||
//UINFO(9, "vlArgRec "<<"oprefix="<<info.m_oprefix<<" osuffix="<<info.m_osuffix
|
||||
// <<" oref="<<info.m_oref<<" "<<dtypep);
|
||||
return info;
|
||||
} else {
|
||||
v3fatalSrc("Unknown data type in var type emitter: "<<dtypep->prettyName());
|
||||
}
|
||||
|
@ -1411,9 +1411,8 @@ public:
|
||||
const MTaskIdSet& mtaskIds() const { return m_mtaskIds; }
|
||||
string mtasksString() const;
|
||||
private:
|
||||
class VlArgTypeRecurseInfo;
|
||||
string vlArgTypeRecurse(AstNodeDType* dtypep, VlArgTypeRecurseInfo* infop,
|
||||
const string& oarray) const;
|
||||
class VlArgTypeRecursed;
|
||||
VlArgTypeRecursed vlArgTypeRecurse(bool forFunc, const AstNodeDType* dtypep) const;
|
||||
};
|
||||
|
||||
class AstDefParam : public AstNode {
|
||||
|
184
src/V3EmitC.cpp
184
src/V3EmitC.cpp
@ -1264,7 +1264,99 @@ class EmitCImp : EmitCStmts {
|
||||
|
||||
// METHODS
|
||||
// Low level
|
||||
void emitVarReset(AstVar* varp);
|
||||
void emitVarReset(AstVar* varp) {
|
||||
AstNodeDType* dtypep = varp->dtypep()->skipRefp();
|
||||
if (varp->isIO() && m_modp->isTop() && optSystemC()) {
|
||||
// System C top I/O doesn't need loading, as the lower level subinst code does it.}
|
||||
} else if (varp->isParam()) {
|
||||
UASSERT_OBJ(varp->valuep(), varp, "No init for a param?");
|
||||
// If a simple CONST value we initialize it using an enum
|
||||
// If an ARRAYINIT we initialize it using an initial block similar to a signal
|
||||
//puts("// parameter "+varp->nameProtect()+" = "+varp->valuep()->name()+"\n");
|
||||
} else if (AstInitArray* initarp = VN_CAST(varp->valuep(), InitArray)) {
|
||||
if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
|
||||
if (initarp->defaultp()) {
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi=0;");
|
||||
puts(" for (; __Vi<"+cvtToStr(adtypep->elementsConst()));
|
||||
puts("; ++__Vi) {\n");
|
||||
emitSetVarConstant(varp->nameProtect()+"[__Vi]",
|
||||
VN_CAST(initarp->defaultp(), Const));
|
||||
puts("}}\n");
|
||||
}
|
||||
const AstInitArray::KeyItemMap& mapr = initarp->map();
|
||||
for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin();
|
||||
it != mapr.end(); ++it) {
|
||||
AstNode* valuep = it->second->valuep();
|
||||
emitSetVarConstant(varp->nameProtect()
|
||||
+"["+cvtToStr(it->first)+"]",
|
||||
VN_CAST(valuep, Const));
|
||||
}
|
||||
} else {
|
||||
varp->v3fatalSrc("InitArray under non-arrayed var");
|
||||
}
|
||||
} else {
|
||||
puts(emitVarResetRecurse(varp, dtypep, 0, ""));
|
||||
}
|
||||
}
|
||||
string emitVarResetRecurse(AstVar* varp, AstNodeDType* dtypep, int depth, string suffix) {
|
||||
dtypep = dtypep->skipRefp();
|
||||
AstBasicDType* basicp = dtypep->basicp();
|
||||
// Returns string to do resetting, empty to do nothing (which caller should handle)
|
||||
if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
|
||||
UASSERT_OBJ(adtypep->msb() >= adtypep->lsb(), varp,
|
||||
"Should have swapped msb & lsb earlier.");
|
||||
string ivar = string("__Vi")+cvtToStr(depth);
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
string pre = ("{ int "+ivar+"="+cvtToStr(0)+";"
|
||||
+" for (; "+ivar+"<"+cvtToStr(adtypep->elementsConst())
|
||||
+"; ++"+ivar+") {\n");
|
||||
string below = emitVarResetRecurse(varp, adtypep->subDTypep(), depth+1, suffix+"["+ivar+"]");
|
||||
string post = "}}\n";
|
||||
return below.empty() ? "" : pre + below + post;
|
||||
}
|
||||
else if (basicp && basicp->keyword() == AstBasicDTypeKwd::STRING) {
|
||||
// String's constructor deals with it
|
||||
return "";
|
||||
}
|
||||
else if (basicp) {
|
||||
bool zeroit = (varp->attrFileDescr() // Zero so we don't core dump if never $fopen
|
||||
|| (basicp && basicp->isZeroInit())
|
||||
|| (v3Global.opt.underlineZero()
|
||||
&& !varp->name().empty() && varp->name()[0] == '_')
|
||||
|| (v3Global.opt.xInitial() == "fast"
|
||||
|| v3Global.opt.xInitial() == "0"));
|
||||
splitSizeInc(1);
|
||||
if (dtypep->isWide()) { // Handle unpacked; not basicp->isWide
|
||||
string out;
|
||||
if (zeroit) out += "VL_ZERO_RESET_W(";
|
||||
else out += "VL_RAND_RESET_W(";
|
||||
out += cvtToStr(dtypep->widthMin());
|
||||
out += ", "+varp->nameProtect()+suffix+");\n";
|
||||
return out;
|
||||
} else {
|
||||
string out = varp->nameProtect() + suffix;
|
||||
// If --x-initial-edge is set, we want to force an initial
|
||||
// edge on uninitialized clocks (from 'X' to whatever the
|
||||
// first value is). Since the class is instantiated before
|
||||
// initial blocks are evaluated, this should not clash
|
||||
// with any initial block settings.
|
||||
if (zeroit || (v3Global.opt.xInitialEdge() && varp->isUsedClock())) {
|
||||
out += " = 0;\n";
|
||||
} else {
|
||||
out += " = VL_RAND_RESET_";
|
||||
out += dtypep->charIQWN();
|
||||
out += "("+ cvtToStr(dtypep->widthMin())+");\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
else {
|
||||
v3fatalSrc("Unknown node type in reset generator: "<<varp->prettyTypeName());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void emitCellCtors(AstNodeModule* modp);
|
||||
void emitSensitives();
|
||||
// Medium level
|
||||
@ -1303,8 +1395,8 @@ public:
|
||||
|
||||
void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
|
||||
AstBasicDType* basicp = nodep->basicp();
|
||||
UASSERT_OBJ(basicp, nodep, "Unimplemented: Outputting this data type");
|
||||
if (nodep->isIO() && nodep->isSc()) {
|
||||
UASSERT_OBJ(basicp, nodep, "Unimplemented: Outputting this data type");
|
||||
m_ctorVarsVec.push_back(nodep);
|
||||
if (nodep->attrScClocked() && nodep->isReadOnly()) {
|
||||
puts("sc_in_clk ");
|
||||
@ -1698,94 +1790,6 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
//######################################################################
|
||||
// Internal EmitC
|
||||
|
||||
void EmitCImp::emitVarReset(AstVar* varp) {
|
||||
if (varp->isIO() && m_modp->isTop() && optSystemC()) {
|
||||
// System C top I/O doesn't need loading, as the lower level subinst code does it.}
|
||||
} else if (varp->isParam()) {
|
||||
UASSERT_OBJ(varp->valuep(), varp, "No init for a param?");
|
||||
// If a simple CONST value we initialize it using an enum
|
||||
// If an ARRAYINIT we initialize it using an initial block similar to a signal
|
||||
//puts("// parameter "+varp->nameProtect()+" = "+varp->valuep()->name()+"\n");
|
||||
}
|
||||
else if (AstInitArray* initarp = VN_CAST(varp->valuep(), InitArray)) {
|
||||
if (AstUnpackArrayDType* arrayp = VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType)) {
|
||||
if (initarp->defaultp()) {
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi=0;");
|
||||
puts(" for (; __Vi<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++__Vi) {\n");
|
||||
emitSetVarConstant(varp->nameProtect()+"[__Vi]",
|
||||
VN_CAST(initarp->defaultp(), Const));
|
||||
puts("}}\n");
|
||||
}
|
||||
const AstInitArray::KeyItemMap& mapr = initarp->map();
|
||||
for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin();
|
||||
it != mapr.end(); ++it) {
|
||||
AstNode* valuep = it->second->valuep();
|
||||
emitSetVarConstant(varp->nameProtect()
|
||||
+"["+cvtToStr(it->first)+"]",
|
||||
VN_CAST(valuep, Const));
|
||||
}
|
||||
} else {
|
||||
varp->v3fatalSrc("InitArray under non-arrayed var");
|
||||
}
|
||||
}
|
||||
else if (varp->basicp() && varp->basicp()->keyword() == AstBasicDTypeKwd::STRING) {
|
||||
// Constructor deals with it
|
||||
}
|
||||
else {
|
||||
int vects = 0;
|
||||
// This isn't very robust and may need cleanup for other data types
|
||||
for (AstUnpackArrayDType* arrayp=VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType);
|
||||
arrayp;
|
||||
arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) {
|
||||
int vecnum = vects++;
|
||||
UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp,
|
||||
"Should have swapped msb & lsb earlier.");
|
||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";");
|
||||
puts(" for (; "+ivar+"<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++"+ivar+") {\n");
|
||||
}
|
||||
bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen
|
||||
|| (varp->basicp() && varp->basicp()->isZeroInit())
|
||||
|| (v3Global.opt.underlineZero()
|
||||
&& !varp->name().empty() && varp->name()[0]=='_')
|
||||
|| (v3Global.opt.xInitial() == "fast" || v3Global.opt.xInitial() == "0"));
|
||||
if (varp->isWide()) {
|
||||
// DOCUMENT: We randomize everything. If the user wants a _var to be zero,
|
||||
// there should be a initial statement. (Different from verilator2.)
|
||||
if (zeroit) puts("VL_ZERO_RESET_W(");
|
||||
else puts("VL_RAND_RESET_W(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(",");
|
||||
puts(varp->nameProtect());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts(");\n");
|
||||
} else {
|
||||
puts(varp->nameProtect());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
// If --x-initial-edge is set, we want to force an initial
|
||||
// edge on uninitialized clocks (from 'X' to whatever the
|
||||
// first value is). Since the class is instantiated before
|
||||
// initial blocks are evaluated, this should not clash
|
||||
// with any initial block settings.
|
||||
if (zeroit || (v3Global.opt.xInitialEdge() && varp->isUsedClock())) {
|
||||
puts(" = 0;\n");
|
||||
} else {
|
||||
puts(" = VL_RAND_RESET_");
|
||||
emitIQW(varp);
|
||||
puts("(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(");\n");
|
||||
}
|
||||
}
|
||||
for (int v=0; v<vects; ++v) puts( "}}\n");
|
||||
}
|
||||
splitSizeInc(1);
|
||||
}
|
||||
|
||||
void EmitCImp::emitCoverageDecl(AstNodeModule* modp) {
|
||||
if (v3Global.opt.coverage()) {
|
||||
ofp()->putsPrivate(true);
|
||||
|
@ -113,17 +113,17 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep,
|
||||
AstNodeRange* prevp = VN_CAST(nrangep->backp(), NodeRange);
|
||||
if (prevp) nrangep->unlinkFrBack();
|
||||
AstRange* rangep = VN_CAST(nrangep, Range);
|
||||
if (!rangep) {
|
||||
UASSERT_OBJ(VN_IS(nrangep, UnsizedRange), nrangep,
|
||||
"Expected range or unsized range");
|
||||
arrayp = new AstUnsizedArrayDType
|
||||
(nrangep->fileline(), VFlagChildDType(), arrayp);
|
||||
} else if (isPacked) {
|
||||
if (rangep && isPacked) {
|
||||
arrayp = new AstPackArrayDType
|
||||
(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
|
||||
} else {
|
||||
} else if (rangep) {
|
||||
arrayp = new AstUnpackArrayDType
|
||||
(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
|
||||
} else if (VN_IS(nrangep, UnsizedRange)) {
|
||||
arrayp = new AstUnsizedArrayDType
|
||||
(nrangep->fileline(), VFlagChildDType(), arrayp);
|
||||
} else {
|
||||
UASSERT_OBJ(0, nrangep, "Expected range or unsized range");
|
||||
}
|
||||
nrangep = prevp;
|
||||
}
|
||||
|
@ -388,7 +388,8 @@ private:
|
||||
// Any strings sent to a display must be var of string data type,
|
||||
// to avoid passing a pointer to a temporary.
|
||||
for (AstNode* expp=nodep->exprsp(); expp; expp = expp->nextp()) {
|
||||
if (expp->dtypep()->basicp()->isString()
|
||||
if (expp->dtypep()->basicp()
|
||||
&& expp->dtypep()->basicp()->isString()
|
||||
&& !VN_IS(expp, VarRef)) {
|
||||
createDeepTemp(expp, true);
|
||||
}
|
||||
|
@ -1358,7 +1358,7 @@ private:
|
||||
// Note genvar's are also entered as integers
|
||||
nodep->dtypeFrom(nodep->varp());
|
||||
if (VN_IS(nodep->backp(), NodeAssign) && nodep->lvalue()) { // On LHS
|
||||
UASSERT_OBJ(nodep->widthMin(), nodep, "LHS var should be size complete");
|
||||
UASSERT_OBJ(nodep->dtypep(), nodep, "LHS var should be dtype completed");
|
||||
}
|
||||
//if (debug()>=9) nodep->dumpTree(cout, " VRout ");
|
||||
if (nodep->lvalue() && nodep->varp()->direction() == VDirection::CONSTREF) {
|
||||
@ -1631,6 +1631,7 @@ private:
|
||||
|
||||
virtual void visit(AstMethodCall* nodep) {
|
||||
UINFO(5," METHODSEL "<<nodep<<endl);
|
||||
if (nodep->didWidth()) return;
|
||||
if (debug()>=9) nodep->dumpTree("-mts-in: ");
|
||||
// Should check types the method requires, but at present we don't do much
|
||||
userIterate(nodep->fromp(), WidthVP(SELF, BOTH).p());
|
||||
@ -2308,10 +2309,10 @@ private:
|
||||
}
|
||||
case 'p': { // Packed
|
||||
AstBasicDType* basicp = argp ? argp->dtypep()->basicp() : NULL;
|
||||
if (basicp->isString()) {
|
||||
if (basicp && basicp->isString()) {
|
||||
added = true;
|
||||
newFormat += "\"%@\"";
|
||||
} else if (basicp->isDouble()) {
|
||||
} else if (basicp && basicp->isDouble()) {
|
||||
added = true;
|
||||
newFormat += "%g";
|
||||
} else {
|
||||
@ -3482,6 +3483,16 @@ private:
|
||||
}
|
||||
if (underp) {} // cppcheck
|
||||
}
|
||||
void iterateCheckTyped(AstNode* nodep, const char* side, AstNode* underp,
|
||||
AstNodeDType* expDTypep, Stage stage) {
|
||||
if (stage & PRELIM) {
|
||||
underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, PRELIM).p());
|
||||
}
|
||||
if (stage & FINAL) {
|
||||
underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
|
||||
}
|
||||
if (underp) {} // cppcheck
|
||||
}
|
||||
void iterateCheckSizedSelf(AstNode* nodep, const char* side, AstNode* underp,
|
||||
Determ determ, Stage stage) {
|
||||
// Coerce child to any sized-number data type; child is self-determined
|
||||
|
Loading…
Reference in New Issue
Block a user