diff options
author | heterodoxic <122719743+heterodoxic@users.noreply.github.com> | 2023-04-28 10:30:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-28 10:30:16 +0200 |
commit | 91abf35442d6f0861db659c5332b481bd24dfedb (patch) | |
tree | 4cf634f6d1670d92b28e05174564252f22f6ec70 | |
parent | 560fa9a1fe3c098e00ca6486b425951a3a8cd568 (diff) | |
download | Nim-91abf35442d6f0861db659c5332b481bd24dfedb.tar.gz |
improve C/C++ debug output readability (1/N) (#21690)
* hacky attempt to reconcile default explicit constructors with enforcement of brace initialization, instead of memsetting imported objects to 0 * improve C/C++ debug output readability (1/N)
-rw-r--r-- | compiler/ccgexprs.nim | 80 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 75 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 36 | ||||
-rw-r--r-- | compiler/cgen.nim | 97 |
4 files changed, 159 insertions, 129 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 5a8e2d296..1767edb8c 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -199,12 +199,12 @@ proc canMove(p: BProc, n: PNode; dest: TLoc): bool = proc genRefAssign(p: BProc, dest, src: TLoc) = if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config): - linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) elif dest.storage == OnHeap: - linefmt(p, cpsStmts, "#asgnRef((void**) $1, $2);$n", + linefmt(p, cpsStmts, "#asgnRef((void**) $1, $2);\n", [addrLoc(p.config, dest), rdLoc(src)]) else: - linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", + linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);\n", [addrLoc(p.config, dest), rdLoc(src)]) proc asgnComplexity(n: PNode): int = @@ -270,19 +270,19 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = # (for objects, etc.): if optSeqDestructors in p.config.globalOptions: linefmt(p, cpsStmts, - "$1 = $2;$n", + "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) elif needToCopy notin flags or tfShallow in skipTypes(dest.t, abstractVarRange).flags: if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config): linefmt(p, cpsStmts, - "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n", + "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($3));\n", [addrLoc(p.config, dest), addrLoc(p.config, src), rdLoc(dest)]) else: - linefmt(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n", + linefmt(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);\n", [addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfoV1(p.module, dest.t, dest.lode.info)]) else: - linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n", + linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);\n", [addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfoV1(p.module, dest.t, dest.lode.info)]) proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc) = @@ -318,7 +318,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = # the assignment operation in C. if src.t != nil and src.t.kind == tyPtr: # little HACK to support the new 'var T' as return type: - linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) return let ty = skipTypes(dest.t, abstractRange + tyUserTypeClasses + {tyStatic}) case ty.kind @@ -330,7 +330,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = elif (needToCopy notin flags and src.storage != OnStatic) or canMove(p, src.lode, dest): genRefAssign(p, dest, src) else: - linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n", + linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);\n", [addrLoc(p.config, dest), rdLoc(src), genTypeInfoV1(p.module, dest.t, dest.lode.info)]) of tyString: @@ -340,16 +340,16 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = genRefAssign(p, dest, src) else: if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config): - linefmt(p, cpsStmts, "$1 = #copyString($2);$n", [dest.rdLoc, src.rdLoc]) + linefmt(p, cpsStmts, "$1 = #copyString($2);\n", [dest.rdLoc, src.rdLoc]) elif dest.storage == OnHeap: # we use a temporary to care for the dreaded self assignment: var tmp: TLoc getTemp(p, ty, tmp) - linefmt(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n", + linefmt(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);\n", [dest.rdLoc, src.rdLoc, tmp.rdLoc]) - linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", [tmp.rdLoc]) + linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);\n", [tmp.rdLoc]) else: - linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n", + linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));\n", [addrLoc(p.config, dest), rdLoc(src)]) of tyProc: if containsGarbageCollectedRef(dest.t): @@ -357,19 +357,19 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = let a = optAsgnLoc(dest, dest.t, "ClE_0".rope) let b = optAsgnLoc(src, dest.t, "ClE_0".rope) genRefAssign(p, a, b) - linefmt(p, cpsStmts, "$1.ClP_0 = $2.ClP_0;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1.ClP_0 = $2.ClP_0;\n", [rdLoc(dest), rdLoc(src)]) else: - linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) of tyTuple: if containsGarbageCollectedRef(dest.t): if dest.t.len <= 4: genOptAsgnTuple(p, dest, src, flags) else: genGenericAsgn(p, dest, src, flags) else: - linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) of tyObject: # XXX: check for subtyping? if ty.isImportedCppType: - linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) elif not isObjLackingTypeField(ty): genGenericAsgn(p, dest, src, flags) elif containsGarbageCollectedRef(ty): @@ -380,13 +380,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = else: genGenericAsgn(p, dest, src, flags) else: - linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) of tyArray: if containsGarbageCollectedRef(dest.t) and p.config.selectedGC notin {gcArc, gcOrc, gcHooks}: genGenericAsgn(p, dest, src, flags) else: linefmt(p, cpsStmts, - "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n", + "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($3));\n", [rdLoc(dest), rdLoc(src), getTypeDesc(p.module, dest.t)]) of tyOpenArray, tyVarargs: # open arrays are always on the stack - really? What if a sequence is @@ -395,30 +395,30 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = genOpenArrayConv(p, dest, src) elif containsGarbageCollectedRef(dest.t): linefmt(p, cpsStmts, # XXX: is this correct for arrays? - "#genericAssignOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n", + "#genericAssignOpenArray((void*)$1, (void*)$2, $1Len_0, $3);\n", [addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfoV1(p.module, dest.t, dest.lode.info)]) else: linefmt(p, cpsStmts, # bug #4799, keep the nimCopyMem for a while - #"#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len_0);$n", - "$1 = $2;$n", + #"#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len_0);\n", + "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) of tySet: if mapSetType(p.config, ty) == ctArray: - linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);$n", + linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);\n", [rdLoc(dest), rdLoc(src), getSize(p.config, dest.t)]) else: - linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCstring, tyInt..tyUInt64, tyRange, tyVar, tyLent, tyNil: - linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) else: internalError(p.config, "genAssignment: " & $ty.kind) if optMemTracker in p.options and dest.storage in {OnHeap, OnUnknown}: #writeStackTrace() #echo p.currLineInfo, " requesting" - linefmt(p, cpsStmts, "#memTrackerWrite((void*)$1, $2, $3, $4);$n", + linefmt(p, cpsStmts, "#memTrackerWrite((void*)$1, $2, $3, $4);\n", [addrLoc(p.config, dest), getSize(p.config, dest.t), makeCString(toFullPath(p.config, p.currLineInfo)), p.currLineInfo.safeLineNm]) @@ -437,32 +437,32 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) = case ty.kind of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray: # XXX optimize this - linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n", + linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);\n", [addrLoc(p.config, dest), addrLocOrTemp(src), genTypeInfoV1(p.module, dest.t, dest.lode.info)]) of tySequence, tyString: if optTinyRtti in p.config.globalOptions: - linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n", + linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);\n", [addrLoc(p.config, dest), addrLocOrTemp(src), genTypeInfoV1(p.module, dest.t, dest.lode.info)]) else: - linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n", + linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);\n", [addrLoc(p.config, dest), rdLoc(src), genTypeInfoV1(p.module, dest.t, dest.lode.info)]) of tyOpenArray, tyVarargs: linefmt(p, cpsStmts, - "#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n", + "#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len_0, $3);\n", [addrLoc(p.config, dest), addrLocOrTemp(src), genTypeInfoV1(p.module, dest.t, dest.lode.info)]) of tySet: if mapSetType(p.config, ty) == ctArray: - linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);$n", + linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);\n", [rdLoc(dest), rdLoc(src), getSize(p.config, dest.t)]) else: - linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) of tyPointer, tyChar, tyBool, tyEnum, tyCstring, tyInt..tyUInt64, tyRange, tyVar, tyLent: - linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [rdLoc(dest), rdLoc(src)]) else: internalError(p.config, "genDeepCopy: " & $ty.kind) proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) = @@ -507,14 +507,14 @@ proc binaryStmt(p: BProc, e: PNode, d: var TLoc, op: string) = if d.k != locNone: internalError(p.config, e.info, "binaryStmt") initLocExpr(p, e[1], a) initLocExpr(p, e[2], b) - lineCg(p, cpsStmts, "$1 $2 $3;$n", [rdLoc(a), op, rdLoc(b)]) + lineCg(p, cpsStmts, "$1 $2 $3;\n", [rdLoc(a), op, rdLoc(b)]) proc binaryStmtAddr(p: BProc, e: PNode, d: var TLoc, cpname: string) = var a, b: TLoc if d.k != locNone: internalError(p.config, e.info, "binaryStmtAddr") initLocExpr(p, e[1], a) initLocExpr(p, e[2], b) - lineCg(p, cpsStmts, "#$1($2, $3);$n", [cpname, byRefLoc(p, a), rdLoc(b)]) + lineCg(p, cpsStmts, "#$1($2, $3);\n", [cpname, byRefLoc(p, a), rdLoc(b)]) template unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a: TLoc @@ -1193,9 +1193,9 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = expr(p, e[1], tmp) L = getLabel(p) if m == mOr: - lineF(p, cpsStmts, "if ($1) goto $2;$n", [rdLoc(tmp), L]) + lineF(p, cpsStmts, "if ($1) goto $2;\n", [rdLoc(tmp), L]) else: - lineF(p, cpsStmts, "if (!($1)) goto $2;$n", [rdLoc(tmp), L]) + lineF(p, cpsStmts, "if (!($1)) goto $2;\n", [rdLoc(tmp), L]) expr(p, e[2], tmp) fixLabel(p, L) if d.k == locNone: @@ -1276,15 +1276,15 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e[i + 1], a) if skipTypes(e[i + 1].typ, abstractVarRange).kind == tyChar: inc(L) - appends.add(ropecg(p.module, "#appendChar($1, $2);$n", [strLoc(p, tmp), rdLoc(a)])) + appends.add(ropecg(p.module, "#appendChar($1, $2);\n", [strLoc(p, tmp), rdLoc(a)])) else: if e[i + 1].kind in {nkStrLit..nkTripleStrLit}: inc(L, e[i + 1].strVal.len) else: lens.add(lenExpr(p, a)) lens.add(" + ") - appends.add(ropecg(p.module, "#appendString($1, $2);$n", [strLoc(p, tmp), rdLoc(a)])) - linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, L]) + appends.add(ropecg(p.module, "#appendString($1, $2);\n", [strLoc(p, tmp), rdLoc(a)])) + linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);\n", [tmp.r, lens, L]) p.s(cpsStmts).add appends if d.k == locNone: d = tmp diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 63fb17527..22428a749 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -61,7 +61,7 @@ proc startBlockInternal(p: BProc): int {.discardable.} = p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16 p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16 -template startBlock(p: BProc, start: FormatStr = "{$n", +template startBlock(p: BProc, start: FormatStr = "{\n", args: varargs[Rope]): int = lineCg(p, cpsStmts, start, args) startBlockInternal(p) @@ -173,7 +173,8 @@ proc endBlock(p: BProc) = if p.blocks[topBlock].label.len != 0: blockEnd.addf("} $1: ;$n", [p.blocks[topBlock].label]) else: - blockEnd.addf("}$n", []) + #blockEnd.addf("}$n", []) + blockEnd.add("}\n") endBlock(p, blockEnd) proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} = @@ -346,12 +347,12 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) = assert(typ.len == typ.n.len) genOtherArg(p, value, i, typ, params, argsCounter) if params.len == 0: - lineF(p, cpsStmts, "$#;$n", [decl]) + lineF(p, cpsStmts, "$#;\n", [decl]) else: - lineF(p, cpsStmts, "$#($#);$n", [decl, params]) + lineF(p, cpsStmts, "$#($#);\n", [decl, params]) else: initLocExprSingleUse(p, value, tmp) - lineF(p, cpsStmts, "$# = $#;$n", [decl, tmp.rdLoc]) + lineF(p, cpsStmts, "$# = $#;\n", [decl, tmp.rdLoc]) return assignLocalVar(p, vn) initLocalVar(p, v, imm) @@ -446,9 +447,9 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) = [rdLoc(a), lelse]) if p.module.compileToCpp: # avoid "jump to label crosses initialization" error: - p.s(cpsStmts).add "{" + p.s(cpsStmts).add "{\n" expr(p, it[1], d) - p.s(cpsStmts).add "}" + p.s(cpsStmts).add "}\n" else: expr(p, it[1], d) endBlock(p) @@ -607,13 +608,13 @@ proc genWhileStmt(p: BProc, t: PNode) = loopBody = loopBody[1] genComputedGoto(p, loopBody) else: - p.breakIdx = startBlock(p, "while (1) {$n") + p.breakIdx = startBlock(p, "while (1) {\n") p.blocks[p.breakIdx].isLoop = true initLocExpr(p, t[0], a) if (t[0].kind != nkIntLit) or (t[0].intVal == 0): lineF(p, cpsStmts, "if (!$1) goto ", [rdLoc(a)]) assignLabel(p.blocks[p.breakIdx], p.s(cpsStmts)) - appcg(p, cpsStmts, ";$n", []) + appcg(p, cpsStmts, ";\n", []) genStmts(p, loopBody) if optProfiler in p.options: @@ -977,8 +978,8 @@ proc genCase(p: BProc, t: PNode, d: var TLoc) = of tyCstring: genStringCase(p, t, tyCstring, d) of tyFloat..tyFloat128: - genCaseGeneric(p, t, d, "if ($1 >= $2 && $1 <= $3) goto $4;$n", - "if ($1 == $2) goto $3;$n") + genCaseGeneric(p, t, d, "if ($1 >= $2 && $1 <= $3) goto $4;\n", + "if ($1 == $2) goto $3;\n") else: if t[0].kind == nkSym and sfGoto in t[0].sym.flags: genGotoForCase(p, t) @@ -989,9 +990,9 @@ proc genRestoreFrameAfterException(p: BProc) = if optStackTrace in p.module.config.options: if hasCurFramePointer notin p.flags: p.flags.incl hasCurFramePointer - p.procSec(cpsLocals).add(ropecg(p.module, "\tTFrame* _nimCurFrame;$n", [])) - p.procSec(cpsInit).add(ropecg(p.module, "\t_nimCurFrame = #getFrame();$n", [])) - linefmt(p, cpsStmts, "#setFrame(_nimCurFrame);$n", []) + p.procSec(cpsLocals).add(ropecg(p.module, "\tTFrame* _nimCurFrame;\n", [])) + p.procSec(cpsInit).add(ropecg(p.module, "\t_nimCurFrame = #getFrame();\n", [])) + linefmt(p, cpsStmts, "#setFrame(_nimCurFrame);\n", []) proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = #[ code to generate: @@ -1027,25 +1028,26 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = inc(p.labels, 2) let etmp = p.labels - p.procSec(cpsInit).add(ropecg(p.module, "\tstd::exception_ptr T$1_ = nullptr;", [etmp])) + p.procSec(cpsInit).add(ropecg(p.module, "\tstd::exception_ptr T$1_ = nullptr;\n", [etmp])) let fin = if t[^1].kind == nkFinally: t[^1] else: nil p.nestedTryStmts.add((fin, false, 0.Natural)) if t.kind == nkHiddenTryStmt: - lineCg(p, cpsStmts, "try {$n", []) + lineCg(p, cpsStmts, "try {\n", []) expr(p, t[0], d) - lineCg(p, cpsStmts, "}$n", []) + lineCg(p, cpsStmts, "}\n", []) else: - startBlock(p, "try {$n") + startBlock(p, "try {\n") expr(p, t[0], d) endBlock(p) - # First pass: handle Nim based exceptions: - lineCg(p, cpsStmts, "catch (#Exception* T$1_) {$n", [etmp+1]) + # First pass: handle Nim based exceptions: + #lineCg(p, cpsStmts, "catch (#Exception* T$1_) {\n", [etmp+1]) + startBlock(p, "catch (#Exception* T$1_) {\n", rope(etmp+1)) genRestoreFrameAfterException(p) # an unhandled exception happened! - lineCg(p, cpsStmts, "T$1_ = std::current_exception();$n", [etmp]) + lineCg(p, cpsStmts, "T$1_ = std::current_exception();\n", [etmp]) p.nestedTryStmts[^1].inExcept = true var hasImportedCppExceptions = false var i = 1 @@ -1061,9 +1063,9 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = if hasIf: lineF(p, cpsStmts, "else ", []) startBlock(p) # we handled the error: - linefmt(p, cpsStmts, "T$1_ = nullptr;$n", [etmp]) + linefmt(p, cpsStmts, "T$1_ = nullptr;\n", [etmp]) expr(p, t[i][0], d) - linefmt(p, cpsStmts, "#popCurrentException();$n", []) + linefmt(p, cpsStmts, "#popCurrentException();\n", []) endBlock(p) else: var orExpr = newRopeAppender() @@ -1088,24 +1090,25 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = if orExpr.len != 0: if hasIf: - startBlock(p, "else if ($1) {$n", [orExpr]) + startBlock(p, "else if ($1) {\n", [orExpr]) else: - startBlock(p, "if ($1) {$n", [orExpr]) + startBlock(p, "if ($1) {\n", [orExpr]) hasIf = true if exvar != nil: fillLocalName(p, exvar.sym) fillLoc(exvar.sym.loc, locTemp, exvar, OnStack) - linefmt(p, cpsStmts, "$1 $2 = T$3_;$n", [getTypeDesc(p.module, exvar.sym.typ), + linefmt(p, cpsStmts, "$1 $2 = T$3_;\n", [getTypeDesc(p.module, exvar.sym.typ), rdLoc(exvar.sym.loc), rope(etmp+1)]) # we handled the error: - linefmt(p, cpsStmts, "T$1_ = nullptr;$n", [etmp]) + linefmt(p, cpsStmts, "T$1_ = nullptr;\n", [etmp]) expr(p, t[i][^1], d) - linefmt(p, cpsStmts, "#popCurrentException();$n", []) + linefmt(p, cpsStmts, "#popCurrentException();\n", []) endBlock(p) inc(i) if hasIf and not hasElse: - linefmt(p, cpsStmts, "else throw;$n", [etmp]) - linefmt(p, cpsStmts, "}$n", []) + linefmt(p, cpsStmts, "else throw;\n", [etmp]) + #linefmt(p, cpsStmts, "}\n", []) + endBlock(p) # Second pass: handle C++ based exceptions: template genExceptBranchBody(body: PNode) {.dirty.} = @@ -1124,7 +1127,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = if t[i].len == 1: # general except section: - startBlock(p, "catch (...) {", []) + startBlock(p, "catch (...) {\n", []) genExceptBranchBody(t[i][0]) endBlock(p) catchAllPresent = true @@ -1137,11 +1140,11 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:` fillLocalName(p, exvar.sym) fillLoc(exvar.sym.loc, locTemp, exvar, OnStack) - startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, typeNode.typ), rdLoc(exvar.sym.loc)) + startBlock(p, "catch ($1& $2) {\n", getTypeDesc(p.module, typeNode.typ), rdLoc(exvar.sym.loc)) genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type endBlock(p) elif isImportedException(typeNode.typ, p.config): - startBlock(p, "catch ($1&) {$n", getTypeDesc(p.module, t[i][j].typ)) + startBlock(p, "catch ($1&) {\n", getTypeDesc(p.module, t[i][j].typ)) genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type endBlock(p) @@ -1150,14 +1153,14 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = # general finally block: if t.len > 0 and t[^1].kind == nkFinally: if not catchAllPresent: - startBlock(p, "catch (...) {", []) + startBlock(p, "catch (...) {\n", []) genRestoreFrameAfterException(p) - linefmt(p, cpsStmts, "T$1_ = std::current_exception();$n", [etmp]) + linefmt(p, cpsStmts, "T$1_ = std::current_exception();\n", [etmp]) endBlock(p) startBlock(p) genStmts(p, t[^1][0]) - linefmt(p, cpsStmts, "if (T$1_) std::rethrow_exception(T$1_);$n", [etmp]) + linefmt(p, cpsStmts, "if (T$1_) std::rethrow_exception(T$1_);\n", [etmp]) endBlock(p) proc genTryCppOld(p: BProc, t: PNode, d: var TLoc) = diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 1a9a5a766..9757f6aa9 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -524,14 +524,14 @@ proc genRecordFieldsAux(m: BModule; n: PNode, else: unionBody.addf("#pragma pack(push, 1)$nstruct{", []) unionBody.add(a) - unionBody.addf("} $1;$n", [structName]) + unionBody.addf("} $1;\n", [structName]) if tfPacked in rectype.flags and hasAttribute notin CC[m.config.cCompiler].props: - unionBody.addf("#pragma pack(pop)$n", []) + unionBody.addf("#pragma pack(pop)\n", []) else: genRecordFieldsAux(m, k, rectype, check, unionBody, unionPrefix) else: internalError(m.config, "genRecordFieldsAux(record case branch)") if unionBody != "": - result.addf("union{$n$1};$n", [unionBody]) + result.addf("union{\n$1};\n", [unionBody]) of nkSym: let field = n.sym if field.typ.kind == tyVoid: return @@ -548,20 +548,20 @@ proc genRecordFieldsAux(m: BModule; n: PNode, let fieldType = field.loc.lode.typ.skipTypes(abstractInst) if fieldType.kind == tyUncheckedArray: - result.addf("$1 $2[SEQ_DECL_SIZE];$n", + result.addf("\t$1 $2[SEQ_DECL_SIZE];\n", [getTypeDescAux(m, fieldType.elemType, check, skField), sname]) elif fieldType.kind == tySequence: # we need to use a weak dependency here for trecursive_table. - result.addf("$1$3 $2;$n", [getTypeDescWeak(m, field.loc.t, check, skField), sname, noAlias]) + result.addf("\t$1$3 $2;\n", [getTypeDescWeak(m, field.loc.t, check, skField), sname, noAlias]) elif field.bitsize != 0: - result.addf("$1$4 $2:$3;$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, rope($field.bitsize), noAlias]) + result.addf("\t$1$4 $2:$3;\n", [getTypeDescAux(m, field.loc.t, check, skField), sname, rope($field.bitsize), noAlias]) else: # don't use fieldType here because we need the # tyGenericInst for C++ template support if fieldType.isOrHasImportedCppType(): - result.addf("$1$3 $2{};$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias]) + result.addf("\t$1$3 $2{};\n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias]) else: - result.addf("$1$3 $2;$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias]) + result.addf("\t$1$3 $2;\n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias]) else: internalError(m.config, n.info, "genRecordFieldsAux()") proc getRecordFields(m: BModule; typ: PType, check: var IntSet): Rope = @@ -595,36 +595,36 @@ proc getRecordDesc(m: BModule; typ: PType, name: Rope, if typ.kind == tyObject: if typ[0] == nil: if lacksMTypeField(typ): - appcg(m, result, " {$n", []) + appcg(m, result, " {\n", []) else: if optTinyRtti in m.config.globalOptions: - appcg(m, result, " {$n#TNimTypeV2* m_type;$n", []) + appcg(m, result, " {$n#TNimTypeV2* m_type;\n", []) else: - appcg(m, result, " {$n#TNimType* m_type;$n", []) + appcg(m, result, " {$n#TNimType* m_type;\n", []) hasField = true elif m.compileToCpp: - appcg(m, result, " : public $1 {$n", + appcg(m, result, " : public $1 {\n", [getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check, skField)]) if typ.isException and m.config.exc == excCpp: when false: - appcg(m, result, "virtual void raise() { throw *this; }$n", []) # required for polymorphic exceptions + appcg(m, result, "virtual void raise() { throw *this; }\n", []) # required for polymorphic exceptions if typ.sym.magic == mException: # Add cleanup destructor to Exception base class - appcg(m, result, "~$1();$n", [name]) + appcg(m, result, "~$1();\n", [name]) # define it out of the class body and into the procs section so we don't have to # artificially forward-declare popCurrentExceptionEx (very VERY troublesome for HCR) - appcg(m, cfsProcs, "inline $1::~$1() {if(this->raiseId) #popCurrentExceptionEx(this->raiseId);}$n", [name]) + appcg(m, cfsProcs, "inline $1::~$1() {if(this->raiseId) #popCurrentExceptionEx(this->raiseId);}\n", [name]) hasField = true else: - appcg(m, result, " {$n $1 Sup;$n", + appcg(m, result, " {$n $1 Sup;\n", [getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check, skField)]) hasField = true else: - result.addf(" {$n", [name]) + result.addf(" {\n", [name]) let desc = getRecordFields(m, typ, check) if desc == "" and not hasField: - result.addf("char dummy;$n", []) + result.addf("char dummy;\n", []) else: result.add(desc) result.add("};\L") diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 960805e8d..db2f280f1 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -273,7 +273,16 @@ proc safeLineNm(info: TLineInfo): int = proc genCLineDir(r: var Rope, filename: string, line: int; conf: ConfigRef) = assert line >= 0 if optLineDir in conf.options and line > 0: - r.addf("$N#line $2 $1$N", + r.addf("\n#line $2 $1\n", + [rope(makeSingleLineCString(filename)), rope(line)]) + +proc genCLineDir(r: var Rope, filename: string, line: int; p: BProc; info: TLineInfo; lastFileIndex: FileIndex; lastLine: uint16) = + assert line >= 0 + if optLineDir in p.config.options and line > 0: + if lastFileIndex == info.fileIndex: + r.addf("\n#line $1\n", [rope(line)]) + else: + r.addf("\n#line $2 $1\n", [rope(makeSingleLineCString(filename)), rope(line)]) proc genCLineDir(r: var Rope, info: TLineInfo; conf: ConfigRef) = @@ -292,11 +301,18 @@ proc genLineDir(p: BProc, t: PNode) = if optEmbedOrigSrc in p.config.globalOptions: p.s(cpsStmts).add("//" & sourceLine(p.config, t.info) & "\L") - genCLineDir(p.s(cpsStmts), t.info, p.config) if ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and (p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIdx: - if freshLineInfo(p, t.info): - linefmt(p, cpsStmts, "nimln_($1, $2);$n", + let lastFileIndex = p.lastLineInfo.fileIndex + let lastLine = p.lastLineInfo.line + let freshLine = freshLineInfo(p, t.info) + if freshLine: + genCLineDir(p.s(cpsStmts), toFullPath(p.config, t.info), line, p, t.info, lastFileIndex, lastLine) + if lastFileIndex == t.info.fileIndex: + linefmt(p, cpsStmts, "nimln_($1);\n", + [line]) + else: + linefmt(p, cpsStmts, "nimlf_($1, $2);\n", [line, quotedFilename(p.config, t.info)]) proc accessThreadLocalVar(p: BProc, s: PSym) @@ -457,9 +473,9 @@ proc resetLoc(p: BProc, loc: var TLoc) = let atyp = skipTypes(loc.t, abstractInst) if atyp.kind in {tyVar, tyLent}: - linefmt(p, cpsStmts, "$1->len = 0; $1->p = NIM_NIL;$n", [rdLoc(loc)]) + linefmt(p, cpsStmts, "$1->len = 0; $1->p = NIM_NIL;\n", [rdLoc(loc)]) else: - linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)]) + linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;\n", [rdLoc(loc)]) elif not isComplexValueType(typ): if containsGcRef: var nilLoc: TLoc @@ -472,7 +488,7 @@ proc resetLoc(p: BProc, loc: var TLoc) = if loc.storage != OnStack and containsGcRef: specializeReset(p, loc) when false: - linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n", + linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);\n", [addrLoc(p.config, loc), genTypeInfoV1(p.module, loc.t, loc.lode.info)]) # XXX: generated reset procs should not touch the m_type # field, so disabling this should be safe: @@ -480,7 +496,7 @@ proc resetLoc(p: BProc, loc: var TLoc) = else: # array passed as argument decayed into pointer, bug #7332 # so we use getTypeDesc here rather than rdLoc(loc) - linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n", + linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));\n", [addrLoc(p.config, loc), getTypeDesc(p.module, loc.t, mapTypeChooser(loc))]) # XXX: We can be extra clever here and call memset only @@ -490,7 +506,7 @@ proc resetLoc(p: BProc, loc: var TLoc) = proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) = let typ = loc.t if optSeqDestructors in p.config.globalOptions and skipTypes(typ, abstractInst + {tyStatic}).kind in {tyString, tySequence}: - linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)]) + linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;\n", [rdLoc(loc)]) elif not isComplexValueType(typ): if containsGarbageCollectedRef(loc.t): var nilLoc: TLoc @@ -498,14 +514,14 @@ proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) = nilLoc.r = rope("NIM_NIL") genRefAssign(p, loc, nilLoc) else: - linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc), + linefmt(p, cpsStmts, "$1 = ($2)0;\n", [rdLoc(loc), getTypeDesc(p.module, typ, mapTypeChooser(loc))]) else: if not isTemp or containsGarbageCollectedRef(loc.t): # don't use nimZeroMem for temporary values for performance if we can # avoid it: if not isOrHasImportedCppType(typ): - linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n", + linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));\n", [addrLoc(p.config, loc), getTypeDesc(p.module, typ, mapTypeChooser(loc))]) genObjectInit(p, cpsStmts, loc.t, loc, constructObj) @@ -525,9 +541,9 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = inc(p.labels) result.r = "T" & rope(p.labels) & "_" if p.module.compileToCpp and isOrHasImportedCppType(t): - linefmt(p, cpsLocals, "$1 $2{};$n", [getTypeDesc(p.module, t, skVar), result.r]) + linefmt(p, cpsLocals, "$1 $2{};\n", [getTypeDesc(p.module, t, skVar), result.r]) else: - linefmt(p, cpsLocals, "$1 $2;$n", [getTypeDesc(p.module, t, skVar), result.r]) + linefmt(p, cpsLocals, "$1 $2;\n", [getTypeDesc(p.module, t, skVar), result.r]) result.k = locTemp result.lode = lodeTyp t result.storage = OnStack @@ -545,7 +561,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = proc getTempCpp(p: BProc, t: PType, result: var TLoc; value: Rope) = inc(p.labels) result.r = "T" & rope(p.labels) & "_" - linefmt(p, cpsStmts, "$1 $2 = $3;$n", [getTypeDesc(p.module, t, skVar), result.r, value]) + linefmt(p, cpsStmts, "$1 $2 = $3;\n", [getTypeDesc(p.module, t, skVar), result.r, value]) result.k = locTemp result.lode = lodeTyp t result.storage = OnStack @@ -554,7 +570,7 @@ proc getTempCpp(p: BProc, t: PType, result: var TLoc; value: Rope) = proc getIntTemp(p: BProc, result: var TLoc) = inc(p.labels) result.r = "T" & rope(p.labels) & "_" - linefmt(p, cpsLocals, "NI $1;$n", [result.r]) + linefmt(p, cpsLocals, "NI $1;\n", [result.r]) result.k = locTemp result.storage = OnStack result.lode = lodeTyp getSysType(p.module.g.graph, unknownLineInfo, tyInt) @@ -569,7 +585,13 @@ proc localVarDecl(p: BProc; n: PNode): Rope = if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0: result.addf("NIM_ALIGN($1) ", [rope(s.alignment)]) - genCLineDir(result, n.info, p.config) + if optLineDir in p.config.options: + let line = n.info.safeLineNm + let lastFileIndex = p.lastLineInfo.fileIndex + let lastLine = p.lastLineInfo.line + discard freshLineInfo(p, n.info) + genCLineDir(result, toFullPath(p.config, n.info), line, p, n.info, lastFileIndex, lastLine) + addIndent(p, result) result.add getTypeDesc(p.module, s.typ, skVar) if s.constraint.isNil: @@ -587,8 +609,8 @@ proc assignLocalVar(p: BProc, n: PNode) = #assert(s.loc.k == locNone) # not yet assigned # this need not be fulfilled for inline procs; they are regenerated # for each module that uses them! - let nl = if optLineDir in p.config.options: "" else: "\L" - let decl = localVarDecl(p, n) & (if p.module.compileToCpp and isOrHasImportedCppType(n.typ): "{};" else: ";") & nl + #let nl = if optLineDir in p.config.options: "" else: "\n" + let decl = localVarDecl(p, n) & (if p.module.compileToCpp and isOrHasImportedCppType(n.typ): "{};\n" else: ";\n") line(p, cpsLocals, decl) include ccgthreadvars @@ -685,7 +707,8 @@ proc getLabel(p: BProc): TLabel = result = "LA" & rope(p.labels) & "_" proc fixLabel(p: BProc, labl: TLabel) = - lineF(p, cpsStmts, "$1: ;$n", [labl]) + #lineF(p, cpsStmts, "$1: ;$n", [labl]) + p.s(cpsStmts).add("$1: ;$n" % [labl]) proc genVarPrototype(m: BModule, n: PNode) proc requestConstImpl(p: BProc, sym: PSym) @@ -727,14 +750,18 @@ $1define nimfr_(proc, file) \ struct {TFrame* prev;NCSTRING procname;NI line;NCSTRING filename;NI len;VarSlot s[slots];} FR_; \ FR_.procname = proc; FR_.filename = file; FR_.line = 0; FR_.len = length; #nimFrame((TFrame*)&FR_); - $1define nimln_(n, file) \ + $1define nimln_(n) \ + FR_.line = n; + + $1define nimlf_(n, file) \ FR_.line = n; FR_.filename = file; + """ if p.module.s[cfsFrameDefines].len == 0: appcg(p.module, p.module.s[cfsFrameDefines], frameDefines, ["#"]) cgsym(p.module, "nimFrame") - result = ropecg(p.module, "\tnimfr_($1, $2);$n", [procname, filename]) + result = ropecg(p.module, "\tnimfr_($1, $2);\n", [procname, filename]) proc initFrameNoDebug(p: BProc; frame, procname, filename: Rope; line: int): Rope = cgsym(p.module, "nimFrame") @@ -747,7 +774,7 @@ proc deinitFrameNoDebug(p: BProc; frame: Rope): Rope = result = ropecg(p.module, "\t#popFrameOfAddr(&$1);$n", [frame]) proc deinitFrame(p: BProc): Rope = - result = ropecg(p.module, "\t#popFrame();$n", []) + result = ropecg(p.module, "\t#popFrame();\n", []) include ccgexprs @@ -1121,13 +1148,13 @@ proc genProcAux*(m: BModule, prc: PSym) = var decl = localVarDecl(p, resNode) var a: TLoc initLocExprSingleUse(p, val, a) - linefmt(p, cpsStmts, "$1 = $2;$n", [decl, rdLoc(a)]) + linefmt(p, cpsStmts, "$1 = $2;\n", [decl, rdLoc(a)]) else: # declare the result symbol: assignLocalVar(p, resNode) assert(res.loc.r != "") initLocalVar(p, res, immediateAsgn=false) - returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)]) + returnStmt = ropecg(p.module, "\treturn $1;\n", [rdLoc(res.loc)]) else: fillResult(p.config, resNode, prc.typ) assignParam(p, res, prc.typ[0]) @@ -1168,7 +1195,7 @@ proc genProcAux*(m: BModule, prc: PSym) = # This fixes the use of methods and also the case when 2 functions within the same module # call each other using directly the "_actual" versions (an optimization) - see issue #11608 m.s[cfsProcHeaders].addf("$1;\n", [header]) - generatedProc.add ropecg(p.module, "$1 {$n", [header]) + generatedProc.add ropecg(p.module, "$1 {\n", [header]) if optStackTrace in prc.options: generatedProc.add(p.s(cpsLocals)) var procname = makeCString(prc.name.s) @@ -1183,7 +1210,7 @@ proc genProcAux*(m: BModule, prc: PSym) = if beforeRetNeeded in p.flags: generatedProc.add("{") generatedProc.add(p.s(cpsInit)) generatedProc.add(p.s(cpsStmts)) - if beforeRetNeeded in p.flags: generatedProc.add("\t}BeforeRet_: ;\n") + if beforeRetNeeded in p.flags: generatedProc.add("\t}\nBeforeRet_: ;\n") if optStackTrace in prc.options: generatedProc.add(deinitFrame(p)) generatedProc.add(returnStmt) generatedProc.add("}\n") @@ -1452,19 +1479,19 @@ proc genMainProc(m: BModule) = "}$N$N" & "$4" & "N_LIB_PRIVATE void $3PreMain(void) {$N" & - "\t##if $5$N" & # 1 for volatile call, 0 for non-volatile + "##if $5$N" & # 1 for volatile call, 0 for non-volatile "\tvoid (*volatile inner)(void);$N" & "\tinner = $3PreMainInner;$N" & "$1" & "\t(*inner)();$N" & - "\t##else$N" & + "##else$N" & "$1" & "\t$3PreMainInner();$N" & - "\t##endif$N" & + "##endif$N" & "}$N$N" MainProcs = - "\t$^NimMain();$N" + "\t\t$^NimMain();$N" MainProcsWithResult = MainProcs & ("\treturn $1nim_program_result;$N") @@ -1475,17 +1502,17 @@ proc genMainProc(m: BModule) = NimMainProc = "N_CDECL(void, $5NimMain)(void) {$N" & - "\t##if $6$N" & # 1 for volatile call, 0 for non-volatile + "##if $6$N" & # 1 for volatile call, 0 for non-volatile "\tvoid (*volatile inner)(void);$N" & "$4" & "\tinner = $5NimMainInner;$N" & "$2" & "\t(*inner)();$N" & - "\t##else$N" & + "##else$N" & "$4" & "$2" & "\t$5NimMainInner();$N" & - "\t##endif$N" & + "##endif$N" & "}$N$N" NimMainBody = NimMainInner & NimMainProc @@ -1516,7 +1543,7 @@ proc genMainProc(m: BModule) = WinCDllMain = "BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $N" & " LPVOID lpvReserved) {$N" & - "\tif(fwdreason == DLL_PROCESS_ATTACH) {$N" & MainProcs & "}$N" & + "\tif (fwdreason == DLL_PROCESS_ATTACH) {$N" & MainProcs & "\t}$N" & "\treturn 1;$N}$N$N" PosixNimDllMain = WinNimDllMain @@ -1888,7 +1915,7 @@ proc genModule(m: BModule, cfile: Cfile): Rope = if m.s[cfsFrameDefines].len > 0: result.add(m.s[cfsFrameDefines]) else: - result.add("#define nimfr_(x, y)\n#define nimln_(x, y)\n") + result.add("#define nimfr_(x, y)\n#define nimln_(x)\n\n#define nimlf_(x, y)\n") for i in cfsForwardTypes..cfsProcs: if m.s[i].len > 0: |