mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-22 15:25:22 +00:00
use CPU flag instead of thread local storage for the error indicator; progress
This commit is contained in:
@@ -731,9 +731,9 @@ proc raiseExit(p: BProc) =
|
||||
if p.nestedTryStmts.len == 0:
|
||||
p.flags.incl beforeRetNeeded
|
||||
# easy case, simply goto 'ret':
|
||||
lineCg(p, cpsStmts, "if (NIM_UNLIKELY(*nimErr_)) goto BeforeRet_;$n", [])
|
||||
lineCg(p, cpsStmts, "NIM_ERR_JUMP(BeforeRet_);$n", [])
|
||||
else:
|
||||
lineCg(p, cpsStmts, "if (NIM_UNLIKELY(*nimErr_)) goto LA$1_;$n",
|
||||
lineCg(p, cpsStmts, "NIM_ERR_JUMP(LA$1_);$n",
|
||||
[p.nestedTryStmts[^1].label])
|
||||
|
||||
proc finallyActions(p: BProc) =
|
||||
@@ -1282,8 +1282,14 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||
|
||||
expr(p, t[0], d)
|
||||
|
||||
var endLabel = -1
|
||||
if 1 < t.len and t[1].kind == nkExceptBranch:
|
||||
startBlock(p, "if (NIM_UNLIKELY(*nimErr_)) {$n")
|
||||
inc p.labels
|
||||
endLabel = p.labels
|
||||
#startBlock(p, "if (NIM_UNLIKELY(*nimErr_)) {$n")
|
||||
linefmt(p, cpsStmts, "NIM_ERR_JUMP(LA$1_);$n", [lab])
|
||||
linefmt(p, cpsStmts, "goto LA$1_;$n", [endLabel])
|
||||
startBlock(p, "if (NIM_TRUE) {$n") # so that the `else` works out
|
||||
else:
|
||||
startBlock(p)
|
||||
linefmt(p, cpsStmts, "LA$1_:;$n", [lab])
|
||||
@@ -1303,7 +1309,7 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||
if i > 1: lineF(p, cpsStmts, "else", [])
|
||||
startBlock(p)
|
||||
# we handled the exception, remember this:
|
||||
linefmt(p, cpsStmts, "*nimErr_ = NIM_FALSE;$n", [])
|
||||
linefmt(p, cpsStmts, "NIM_ERR_CLEAR();$n", [])
|
||||
expr(p, t[i][0], d)
|
||||
else:
|
||||
var orExpr = newRopeAppender()
|
||||
@@ -1322,7 +1328,7 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||
if i > 1: line(p, cpsStmts, "else ")
|
||||
startBlock(p, "if ($1) {$n", [orExpr])
|
||||
# we handled the exception, remember this:
|
||||
linefmt(p, cpsStmts, "*nimErr_ = NIM_FALSE;$n", [])
|
||||
linefmt(p, cpsStmts, "NIM_ERR_CLEAR();$n", [])
|
||||
expr(p, t[i][^1], d)
|
||||
|
||||
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
||||
@@ -1332,6 +1338,8 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||
inc(i)
|
||||
discard pop(p.nestedTryStmts)
|
||||
endBlock(p)
|
||||
if endLabel >= 0:
|
||||
linefmt(p, cpsStmts, "LA$1_:;$n", [endLabel])
|
||||
|
||||
if i < t.len and t[i].kind == nkFinally:
|
||||
startBlock(p)
|
||||
@@ -1342,7 +1350,17 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||
else:
|
||||
# pretend we did handle the error for the safe execution of the 'finally' section:
|
||||
p.procSec(cpsLocals).add(ropecg(p.module, "NIM_BOOL oldNimErrFin$1_;$n", [lab]))
|
||||
linefmt(p, cpsStmts, "oldNimErrFin$1_ = *nimErr_; *nimErr_ = NIM_FALSE;$n", [lab])
|
||||
|
||||
inc p.labels, 2
|
||||
let fLabel = p.labels-1
|
||||
let tLabel = p.labels
|
||||
|
||||
linefmt(p, cpsStmts, "NIM_ERR_JUMP(LA$1_);$n", [tLabel])
|
||||
linefmt(p, cpsStmts, "oldNimErrFin$1_ = NIM_FALSE; goto LA$2_;$n", [lab, fLabel])
|
||||
linefmt(p, cpsStmts, "LA$2_: oldNimErrFin$1_ = NIM_TRUE; LA$3_: ;$n", [lab, tLabel, fLabel])
|
||||
linefmt(p, cpsStmts, "NIM_ERR_CLEAR();$n", [])
|
||||
|
||||
#linefmt(p, cpsStmts, "oldNimErrFin$1_ = *nimErr_; NIM_ERR_CLEAR();$n", [lab])
|
||||
genStmts(p, t[i][0])
|
||||
# this is correct for all these cases:
|
||||
# 1. finally is run during ordinary control flow
|
||||
@@ -1350,7 +1368,7 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||
# error back to nil.
|
||||
# 3. finally is run for exception handling code without any 'except'
|
||||
# handler present or only handlers that did not match.
|
||||
linefmt(p, cpsStmts, "*nimErr_ = oldNimErrFin$1_;$n", [lab])
|
||||
linefmt(p, cpsStmts, "if (oldNimErrFin$1_) { NIM_ERR_SET(); } else { NIM_ERR_CLEAR(); }$n", [lab])
|
||||
endBlock(p)
|
||||
raiseExit(p)
|
||||
if hasExcept: inc p.withinTryWithExcept
|
||||
|
||||
@@ -1172,8 +1172,9 @@ proc genProcBody(p: BProc; procBody: PNode) =
|
||||
genStmts(p, procBody) # modifies p.locals, p.init, etc.
|
||||
if {nimErrorFlagAccessed, nimErrorFlagDeclared, nimErrorFlagDisabled} * p.flags == {nimErrorFlagAccessed}:
|
||||
p.flags.incl nimErrorFlagDeclared
|
||||
p.blocks[0].sections[cpsLocals].add(ropecg(p.module, "NIM_BOOL* nimErr_;$n", []))
|
||||
p.blocks[0].sections[cpsInit].add(ropecg(p.module, "nimErr_ = #nimErrorFlag();$n", []))
|
||||
p.blocks[0].sections[cpsLocals].add(ropecg(p.module, "NIM_ERR_FLAG();$n", []))
|
||||
if not isDefined(p.config, "nimUseCpuFlag"):
|
||||
p.blocks[0].sections[cpsInit].add(ropecg(p.module, "nimErr_ = #nimErrorFlag();$n", []))
|
||||
|
||||
proc isNoReturn(m: BModule; s: PSym): bool {.inline.} =
|
||||
sfNoReturn in s.flags and m.config.exc != excGoto
|
||||
@@ -1459,6 +1460,9 @@ proc addNimDefines(result: var Rope; conf: ConfigRef) {.inline.} =
|
||||
if conf.isDefined("nimEmulateOverflowChecks"):
|
||||
result.add("#define NIM_EmulateOverflowChecks\L")
|
||||
|
||||
if conf.isDefined("nimUseCpuFlag"):
|
||||
result.add("#define NIM_UseCpuFlag\L")
|
||||
|
||||
proc headerTop(): Rope =
|
||||
result = "/* Generated by Nim Compiler v$1 */$N" % [rope(VersionAsString)]
|
||||
|
||||
|
||||
@@ -594,25 +594,28 @@ NIM_STATIC_ASSERT(sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8, "P
|
||||
#define NIM_NOALIAS __restrict
|
||||
/* __restrict is said to work for all the C(++) compilers out there that we support */
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define NIM_ERR_FLAG() /* nothing to declare: uses HW flag */
|
||||
# define NIM_ERR_JUMP(lab) __asm__ goto("jc %l0" \
|
||||
#if defined(NIM_UseCpuFlag)
|
||||
# if defined(__x86_64__) || defined(__i386__)
|
||||
# define NIM_ERR_FLAG() /* nothing to declare: uses HW flag */
|
||||
# define NIM_ERR_JUMP(lab) __asm__ goto("jc %l0" \
|
||||
: \
|
||||
: \
|
||||
: \
|
||||
: lab)
|
||||
# define NIM_ERR_SET() __asm__ volatile("stc" \
|
||||
# define NIM_ERR_SET() __asm__ volatile("stc" \
|
||||
: \
|
||||
: \
|
||||
: "cc" \
|
||||
)
|
||||
|
||||
# define NIM_ERR_CLEAR() __asm__ volatile("clc" \
|
||||
# define NIM_ERR_CLEAR() __asm__ volatile("clc" \
|
||||
: \
|
||||
: \
|
||||
: "cc" \
|
||||
)
|
||||
|
||||
# else
|
||||
# error "CPU flags not implemented for your platform"
|
||||
# endif
|
||||
#else
|
||||
# define NIM_ERR_FLAG() NIM_BOOL* nimErr_
|
||||
# define NIM_ERR_JUMP(lab) if (NIM_UNLIKELY(*nimErr_)) goto lab
|
||||
|
||||
@@ -472,7 +472,7 @@ proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
|
||||
elif quirkyExceptions or gotoBasedExceptions:
|
||||
pushCurrentException(e)
|
||||
when gotoBasedExceptions:
|
||||
inc nimInErrorMode
|
||||
nimInErrorMode = true
|
||||
else:
|
||||
if excHandler != nil:
|
||||
pushCurrentException(e)
|
||||
|
||||
Reference in New Issue
Block a user