diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 759330a3ebe0f..713ac9f3dc898 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -764,6 +764,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope = genProcParams(m, t, rettype, desc, check, true, true) if not isImportedType(t): if t.callConv != ccClosure: # procedure vars may need a closure! + # this is where seemingly dead-code `N_INLINE_PTR` is used m.s[cfsTypes].addf("typedef $1_PTR($2, $3) $4;$n", [rope(CallingConvToStr[t.callConv]), rettype, result, desc]) else: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index fd14817e0dc7f..b276a085b6af8 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -27,6 +27,10 @@ from lineinfos import warnGcMem, errXMustBeCompileTime, hintDependency, errGenerated, errCannotOpenFile import dynlib +template isGnerateNimFrame(options, sym): bool = + optStackTrace in options and + (optStackTraceNoInline notin options or sym.typ.callConv != ccInline) + when not declared(dynlib.libCandidates): proc libCandidates(s: string, dest: var seq[string]) = ## given a library name pattern `s` write possible library names to `dest`. @@ -265,9 +269,11 @@ proc genLineDir(p: BProc, t: PNode) = p.s(cpsStmts).add(~"//" & sourceLine(p.config, t.info) & "\L") genCLineDir(p.s(cpsStmts), toFullPath(p.config, t.info), line, 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", + # why `sfPure notin p.prc.flags` condition? + (p.prc == nil or (sfPure notin p.prc.flags and isGnerateNimFrame(p.options, p.prc))) and + t.info.fileIndex != InvalidFileIdx and + freshLineInfo(p, t.info): + linefmt(p, cpsStmts, "nimln_($1, $2);$n", [line, quotedFilename(p.config, t.info)]) proc postStmtActions(p: BProc) {.inline.} = @@ -618,17 +624,19 @@ include ccgcalls, "ccgstmts.nim" proc initFrame(p: BProc, procname, filename: Rope): Rope = const frameDefines = """ - $1 define nimfr_(proc, file) \ - TFrame FR_; \ - FR_.procname = proc; FR_.filename = file; FR_.line = 0; FR_.len = 0; #nimFrame(&FR_); - - $1 define nimfrs_(proc, file, slots, length) \ - 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_); - - $1 define nimln_(n, file) \ - FR_.line = n; FR_.filename = file; - """ +$1 define nimfr_(proc, file) \ + TFrame FR_; \ + FR_.procname = proc; FR_.filename = file; FR_.line = 0; FR_.len = 0; #nimFrame(&FR_); + +$1 define nimln_(n, file) \ + FR_.line = n; FR_.filename = file; +""" + #[ + Dead code kept that was used for --debugger:endb, kept comment in case we revive it. +$1 define nimfrs_(proc, file, slots, length) \ + 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_); + ]# if p.module.s[cfsFrameDefines].len == 0: appcg(p.module, p.module.s[cfsFrameDefines], frameDefines, ["#"]) @@ -1046,12 +1054,11 @@ proc genProcAux(m: BModule, prc: PSym) = # 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]) - if optStackTrace in prc.options: - generatedProc.add(p.s(cpsLocals)) + generatedProc.add(p.s(cpsLocals)) + let isNimFrame = isGnerateNimFrame(prc.options, prc) + if isNimFrame: var procname = makeCString(prc.name.s) generatedProc.add(initFrame(p, procname, quotedFilename(p.config, prc.info))) - else: - generatedProc.add(p.s(cpsLocals)) if optProfiler in prc.options: # invoke at proc entry for recursion: appcg(p, cpsInit, "\t#nimProfile();$n", []) @@ -1061,7 +1068,7 @@ proc genProcAux(m: BModule, prc: PSym) = generatedProc.add(p.s(cpsInit)) generatedProc.add(p.s(cpsStmts)) if beforeRetNeeded in p.flags: generatedProc.add(~"\t}BeforeRet_: ;$n") - if optStackTrace in prc.options: generatedProc.add(deinitFrame(p)) + if isNimFrame: generatedProc.add(deinitFrame(p)) generatedProc.add(returnStmt) generatedProc.add(~"}$N") m.s[cfsProcs].add(generatedProc) diff --git a/compiler/commands.nim b/compiler/commands.nim index 935d7e2be5f85..b2f2329710d18 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -119,6 +119,7 @@ const errOnOrOffExpectedButXFound = "'on' or 'off' expected, but '$1' found" errOnOffOrListExpectedButXFound = "'on', 'off' or 'list' expected, but '$1' found" errOffHintsError = "'off', 'hint' or 'error' expected, but '$1' found" + errExpectedButFound = "$1 expected, but '$2' found" proc invalidCmdLineOption(conf: ConfigRef; pass: TCmdLinePass, switch: string, info: TLineInfo) = if switch == " ": localError(conf, info, errInvalidCmdLineOption % "-") @@ -280,6 +281,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool of "hints": result = contains(conf.options, optHints) of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis) of "stacktrace": result = contains(conf.options, optStackTrace) + of "stacktraceNoInline": result = contains(conf.options, optStackTraceNoInline) of "linetrace": result = contains(conf.options, optLineTrace) of "debugger": result = contains(conf.globalOptions, optCDebug) of "profiler": result = contains(conf.options, optProfiler) @@ -528,7 +530,12 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "hints": if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf) of "threadanalysis": processOnOffSwitchG(conf, {optThreadAnalysis}, arg, pass, info) - of "stacktrace": processOnOffSwitch(conf, {optStackTrace}, arg, pass, info) + of "stacktrace": + case arg.normalize + of "","on": conf.options.incl optStackTrace + of "off": conf.options.excl optStackTrace + of "noinline": conf.options.incl {optStackTrace, optStackTraceNoInline} + else: localError(conf, info, errExpectedButFound % ["'', 'on', 'off', 'noinline'", arg]) of "excessivestacktrace": processOnOffSwitchG(conf, {optExcessiveStackTrace}, arg, pass, info) of "linetrace": processOnOffSwitch(conf, {optLineTrace}, arg, pass, info) of "debugger": diff --git a/compiler/options.nim b/compiler/options.nim index 42406272cc206..e4b4b4ad51066 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -28,7 +28,7 @@ type # please make sure we have under 32 options optOverflowCheck, optNilCheck, optRefCheck, optNaNCheck, optInfCheck, optStyleCheck, optAssert, optLineDir, optWarns, optHints, - optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support + optOptimizeSpeed, optOptimizeSize, optStackTrace, optStackTraceNoInline, # stack tracing support optLineTrace, # line tracing support (includes stack tracing) optByRef, # use pass by ref for objects # (for interfacing with C) diff --git a/doc/basicopt.txt b/doc/basicopt.txt index 1405e7b01b8dd..1f3fb8ab3a0a6 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -17,7 +17,8 @@ Options: see: "compile time define pragmas") -u, --undef:SYMBOL undefine a conditional symbol -f, --forceBuild:on|off force rebuilding of all modules - --stackTrace:on|off turn stack tracing on|off + --stackTrace:on|off|noinline turn stack tracing on|off; {.inline.} procs + won't be traceable with `noinline` option --lineTrace:on|off turn line tracing on|off --threads:on|off turn support for multi-threading on|off -x, --checks:on|off turn all runtime checks on|off