Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP #23669

Closed
wants to merge 3 commits into from
Closed

WIP #23669

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions compiler/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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) =
Expand Down Expand Up @@ -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])
Expand All @@ -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()
Expand All @@ -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", [])
Expand All @@ -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)
Expand All @@ -1342,15 1350,25 @@ 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
# 2. finally is run after 'except' block handling: these however set the
# 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
Expand Down Expand Up @@ -1547,14 1565,14 @@ proc genAsmStmt(p: BProc, t: PNode) =
if whichPragma(i) == wAsmSyntax:
asmSyntax = i[1].strVal

if asmSyntax != "" and
if asmSyntax != "" and
not (
asmSyntax == "gcc" and hasGnuAsm in CC[p.config.cCompiler].props or
asmSyntax == "vcc" and hasGnuAsm notin CC[p.config.cCompiler].props):
localError(
p.config, t.info,
p.config, t.info,
"Your compiler does not support the specified inline assembler")

genAsmOrEmitStmt(p, t, isAsmStmt=true, s)
# see bug #2362, "top level asm statements" seem to be a mis-feature
# but even if we don't do this, the example in #2362 cannot possibly
Expand Down
10 changes: 8 additions & 2 deletions compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1280,6 1281,8 @@ proc genProcAux*(m: BModule, prc: PSym) =
if beforeRetNeeded in p.flags: generatedProc.add("{")
generatedProc.add(p.s(cpsInit))
generatedProc.add(p.s(cpsStmts))
if m.config.isDefined("nimUseCpuFlag"):
generatedProc.add("\tNIM_ERR_CLEAR();\n")
if beforeRetNeeded in p.flags: generatedProc.add("\t}BeforeRet_: ;\n")
if optStackTrace in prc.options: generatedProc.add(deinitFrame(p))
generatedProc.add(returnStmt)
Expand Down Expand Up @@ -1459,6 1462,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)]

Expand Down
29 changes: 29 additions & 0 deletions lib/nimbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -863,4 863,33 @@ 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(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" \
: \
: \
: "cc" \
)

# 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
# define NIM_ERR_CLEAR() *nimErr_ = NIM_FALSE
# define NIM_ERR_SET() *nimErr_ = NIM_TRUE
#endif /* __GNUC__ */

#endif /* NIMBASE_H */
13 changes: 11 additions & 2 deletions lib/system/excpt.nim
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 448,9 @@ when gotoBasedExceptions:
## This proc must be called before `currException` is destroyed.
## It also must be called at the end of every thread to ensure no
## error is swallowed.
when defined(nimUseCpuFlag):
var nimInErrorMode = false
{.emit: "NIM_ERR_JUMP(Lerr_); goto Lend_; Lerr_: `nimInErrorMode` = NIM_TRUE; Lend_: ;".}
if nimInErrorMode and currException != nil:
reportUnhandledError(currException)
currException = nil
Expand All @@ -472,7 475,10 @@ proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
elif quirkyExceptions or gotoBasedExceptions:
pushCurrentException(e)
when gotoBasedExceptions:
inc nimInErrorMode
when defined(nimUseCpuFlag):
{.emit: "NIM_ERR_SET();".}
else:
nimInErrorMode = true
else:
if excHandler != nil:
pushCurrentException(e)
Expand Down Expand Up @@ -512,7 518,10 @@ proc reraiseException() {.compilerRtl.} =
sysFatal(ReraiseDefect, "no exception to reraise")
else:
when gotoBasedExceptions:
inc nimInErrorMode
when defined(nimUseCpuFlag):
{.emit: "NIM_ERR_SET();".}
else:
nimInErrorMode = true
else:
raiseExceptionAux(currException)

Expand Down
Loading