make goto based exceptions available for 'nim cpp' (#13244)
* make goto based exceptions available for 'nim cpp' * optimize seq.add to be comparable to C++'s emplace_back
This commit is contained in:
parent
4f3dd33509
commit
6efac70181
11 changed files with 29 additions and 18 deletions
|
|
@ -608,7 +608,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
||||||
elif m.compileToCpp:
|
elif m.compileToCpp:
|
||||||
appcg(m, result, " : public $1 {$n",
|
appcg(m, result, " : public $1 {$n",
|
||||||
[getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check)])
|
[getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check)])
|
||||||
if typ.isException:
|
if typ.isException and m.config.exc == excCpp:
|
||||||
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:
|
if typ.sym.magic == mException:
|
||||||
# Add cleanup destructor to Exception base class
|
# Add cleanup destructor to Exception base class
|
||||||
|
|
|
||||||
|
|
@ -342,7 +342,7 @@ type
|
||||||
|
|
||||||
proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
|
proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
|
||||||
mode: ObjConstrMode) =
|
mode: ObjConstrMode) =
|
||||||
if p.module.compileToCpp and t.isException and not isDefined(p.config, "noCppExceptions"):
|
if p.module.compileToCpp and t.isException and p.config.exc == excCpp:
|
||||||
# init vtable in Exception object for polymorphic exceptions
|
# init vtable in Exception object for polymorphic exceptions
|
||||||
includeHeader(p.module, "<new>")
|
includeHeader(p.module, "<new>")
|
||||||
linefmt(p, section, "new ($1) $2;$n", [rdLoc(a), getTypeDesc(p.module, t)])
|
linefmt(p, section, "new ($1) $2;$n", [rdLoc(a), getTypeDesc(p.module, t)])
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,13 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
|
||||||
# now process command line arguments again, because some options in the
|
# now process command line arguments again, because some options in the
|
||||||
# command line can overwrite the config file's settings
|
# command line can overwrite the config file's settings
|
||||||
extccomp.initVars(conf)
|
extccomp.initVars(conf)
|
||||||
|
# XXX This is hacky. We need to find a better way.
|
||||||
|
case conf.command
|
||||||
|
of "cpp", "compiletocpp":
|
||||||
|
conf.cmd = cmdCompileToCpp
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
self.processCmdLine(passCmd2, "", conf)
|
self.processCmdLine(passCmd2, "", conf)
|
||||||
if conf.command == "":
|
if conf.command == "":
|
||||||
rawMessage(conf, errGenerated, "command missing")
|
rawMessage(conf, errGenerated, "command missing")
|
||||||
|
|
|
||||||
|
|
@ -469,9 +469,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
defineSymbol(conf.symbols, "gcmarkandsweep")
|
defineSymbol(conf.symbols, "gcmarkandsweep")
|
||||||
of "destructors", "arc":
|
of "destructors", "arc":
|
||||||
conf.selectedGC = gcArc
|
conf.selectedGC = gcArc
|
||||||
when true:
|
if conf.cmd != cmdCompileToCpp:
|
||||||
if conf.cmd != cmdCompileToCpp:
|
conf.exc = excGoto
|
||||||
conf.exc = excGoto
|
|
||||||
defineSymbol(conf.symbols, "gcdestructors")
|
defineSymbol(conf.symbols, "gcdestructors")
|
||||||
defineSymbol(conf.symbols, "gcarc")
|
defineSymbol(conf.symbols, "gcarc")
|
||||||
incl conf.globalOptions, optSeqDestructors
|
incl conf.globalOptions, optSeqDestructors
|
||||||
|
|
@ -481,9 +480,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
defineSymbol(conf.symbols, "nimV2")
|
defineSymbol(conf.symbols, "nimV2")
|
||||||
of "orc":
|
of "orc":
|
||||||
conf.selectedGC = gcOrc
|
conf.selectedGC = gcOrc
|
||||||
when true:
|
if conf.cmd != cmdCompileToCpp:
|
||||||
if conf.cmd != cmdCompileToCpp:
|
conf.exc = excGoto
|
||||||
conf.exc = excGoto
|
|
||||||
defineSymbol(conf.symbols, "gcdestructors")
|
defineSymbol(conf.symbols, "gcdestructors")
|
||||||
defineSymbol(conf.symbols, "gcorc")
|
defineSymbol(conf.symbols, "gcorc")
|
||||||
incl conf.globalOptions, optSeqDestructors
|
incl conf.globalOptions, optSeqDestructors
|
||||||
|
|
|
||||||
|
|
@ -185,11 +185,12 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||||
of "c", "cc", "compile", "compiletoc":
|
of "c", "cc", "compile", "compiletoc":
|
||||||
# compile means compileToC currently
|
# compile means compileToC currently
|
||||||
conf.cmd = cmdCompileToC
|
conf.cmd = cmdCompileToC
|
||||||
|
if conf.exc == excNone: conf.exc = excSetjmp
|
||||||
defineSymbol(graph.config.symbols, "c")
|
defineSymbol(graph.config.symbols, "c")
|
||||||
commandCompileToC(graph)
|
commandCompileToC(graph)
|
||||||
of "cpp", "compiletocpp":
|
of "cpp", "compiletocpp":
|
||||||
conf.cmd = cmdCompileToCpp
|
conf.cmd = cmdCompileToCpp
|
||||||
conf.exc = excCpp
|
if conf.exc == excNone: conf.exc = excCpp
|
||||||
defineSymbol(graph.config.symbols, "cpp")
|
defineSymbol(graph.config.symbols, "cpp")
|
||||||
commandCompileToC(graph)
|
commandCompileToC(graph)
|
||||||
of "objc", "compiletooc":
|
of "objc", "compiletooc":
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,7 @@ type
|
||||||
ccTcc, ccPcc, ccUcc, ccIcl, ccIcc, ccClangCl
|
ccTcc, ccPcc, ccUcc, ccIcl, ccIcc, ccClangCl
|
||||||
|
|
||||||
ExceptionSystem* = enum
|
ExceptionSystem* = enum
|
||||||
|
excNone, # no exception system selected yet
|
||||||
excSetjmp, # setjmp based exception handling
|
excSetjmp, # setjmp based exception handling
|
||||||
excCpp, # use C++'s native exception handling
|
excCpp, # use C++'s native exception handling
|
||||||
excGoto, # exception handling based on goto (should become the new default for C)
|
excGoto, # exception handling based on goto (should become the new default for C)
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ const
|
||||||
wAsmNoStackFrame, wDiscardable, wNoInit, wCodegenDecl,
|
wAsmNoStackFrame, wDiscardable, wNoInit, wCodegenDecl,
|
||||||
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
||||||
wConstructor, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy}
|
wConstructor, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy}
|
||||||
converterPragmas* = procPragmas - {wNoDestroy}
|
converterPragmas* = procPragmas
|
||||||
methodPragmas* = procPragmas+{wBase}-{wImportCpp, wNoDestroy}
|
methodPragmas* = procPragmas+{wBase}-{wImportCpp}
|
||||||
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
|
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
|
||||||
wDelegator, wExportNims, wUsed, wPragma}
|
wDelegator, wExportNims, wUsed, wPragma}
|
||||||
macroPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
macroPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||||
|
|
|
||||||
|
|
@ -2187,7 +2187,6 @@ proc evalConstExprAux(module: PSym;
|
||||||
setupGlobalCtx(module, g)
|
setupGlobalCtx(module, g)
|
||||||
var c = PCtx g.vm
|
var c = PCtx g.vm
|
||||||
let oldMode = c.mode
|
let oldMode = c.mode
|
||||||
defer: c.mode = oldMode
|
|
||||||
c.mode = mode
|
c.mode = mode
|
||||||
let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
|
let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
|
||||||
if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info)
|
if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info)
|
||||||
|
|
@ -2198,6 +2197,7 @@ proc evalConstExprAux(module: PSym;
|
||||||
#for i in 0..<c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
|
#for i in 0..<c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||||
result = rawExecute(c, start, tos).regToNode
|
result = rawExecute(c, start, tos).regToNode
|
||||||
if result.info.col < 0: result.info = n.info
|
if result.info.col < 0: result.info = n.info
|
||||||
|
c.mode = oldMode
|
||||||
|
|
||||||
proc evalConstExpr*(module: PSym; g: ModuleGraph; e: PNode): PNode =
|
proc evalConstExpr*(module: PSym; g: ModuleGraph; e: PNode): PNode =
|
||||||
result = evalConstExprAux(module, g, nil, e, emConst)
|
result = evalConstExprAux(module, g, nil, e, emConst)
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ var
|
||||||
currException {.threadvar.}: ref Exception
|
currException {.threadvar.}: ref Exception
|
||||||
gcFramePtr {.threadvar.}: GcFrame
|
gcFramePtr {.threadvar.}: GcFrame
|
||||||
|
|
||||||
when defined(cpp) and not defined(noCppExceptions):
|
when defined(cpp) and not defined(noCppExceptions) and not gotoBasedExceptions:
|
||||||
var
|
var
|
||||||
raiseCounter {.threadvar.}: uint
|
raiseCounter {.threadvar.}: uint
|
||||||
|
|
||||||
|
|
@ -410,7 +410,7 @@ proc reportUnhandledError(e: ref Exception) {.nodestroy.} =
|
||||||
discard()
|
discard()
|
||||||
|
|
||||||
proc nimLeaveFinally() {.compilerRtl.} =
|
proc nimLeaveFinally() {.compilerRtl.} =
|
||||||
when defined(cpp) and not defined(noCppExceptions):
|
when defined(cpp) and not defined(noCppExceptions) and not gotoBasedExceptions:
|
||||||
{.emit: "throw;".}
|
{.emit: "throw;".}
|
||||||
else:
|
else:
|
||||||
if excHandler != nil:
|
if excHandler != nil:
|
||||||
|
|
@ -439,7 +439,7 @@ proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
|
||||||
if not localRaiseHook(e): return
|
if not localRaiseHook(e): return
|
||||||
if globalRaiseHook != nil:
|
if globalRaiseHook != nil:
|
||||||
if not globalRaiseHook(e): return
|
if not globalRaiseHook(e): return
|
||||||
when defined(cpp) and not defined(noCppExceptions):
|
when defined(cpp) and not defined(noCppExceptions) and not gotoBasedExceptions:
|
||||||
if e == currException:
|
if e == currException:
|
||||||
{.emit: "throw;".}
|
{.emit: "throw;".}
|
||||||
else:
|
else:
|
||||||
|
|
@ -544,7 +544,7 @@ proc nimFrame(s: PFrame) {.compilerRtl, inl, raises: [].} =
|
||||||
framePtr = s
|
framePtr = s
|
||||||
if s.calldepth == nimCallDepthLimit: callDepthLimitReached()
|
if s.calldepth == nimCallDepthLimit: callDepthLimitReached()
|
||||||
|
|
||||||
when defined(cpp) and appType != "lib" and
|
when defined(cpp) and appType != "lib" and not gotoBasedExceptions and
|
||||||
not defined(js) and not defined(nimscript) and
|
not defined(js) and not defined(nimscript) and
|
||||||
hostOS != "standalone" and not defined(noCppExceptions):
|
hostOS != "standalone" and not defined(noCppExceptions):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ proc addEntry(entry: LogEntry) =
|
||||||
#inc gLog.count
|
#inc gLog.count
|
||||||
#gLog.disabled = false
|
#gLog.disabled = false
|
||||||
|
|
||||||
proc memTrackerWrite(address: pointer; size: int; file: cstring; line: int) {.compilerProc.} =
|
proc memTrackerWrite(address: pointer; size: int; file: cstring; line: int) {.compilerproc.} =
|
||||||
addEntry LogEntry(op: "write", address: address,
|
addEntry LogEntry(op: "write", address: address,
|
||||||
size: size, file: file, line: line, thread: myThreadId())
|
size: size, file: file, line: line, thread: myThreadId())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ proc grow*[T](x: var seq[T]; newLen: Natural; value: T) =
|
||||||
for i in oldLen .. newLen-1:
|
for i in oldLen .. newLen-1:
|
||||||
xu.p.data[i] = value
|
xu.p.data[i] = value
|
||||||
|
|
||||||
proc add*[T](x: var seq[T]; value: sink T) {.magic: "AppendSeqElem", noSideEffect.} =
|
proc add*[T](x: var seq[T]; value: sink T) {.magic: "AppendSeqElem", noSideEffect, nodestroy.} =
|
||||||
## Generic proc for adding a data item `y` to a container `x`.
|
## Generic proc for adding a data item `y` to a container `x`.
|
||||||
##
|
##
|
||||||
## For containers that have an order, `add` means *append*. New generic
|
## For containers that have an order, `add` means *append*. New generic
|
||||||
|
|
@ -104,6 +104,10 @@ proc add*[T](x: var seq[T]; value: sink T) {.magic: "AppendSeqElem", noSideEffec
|
||||||
if xu.p == nil or xu.p.cap < oldLen+1:
|
if xu.p == nil or xu.p.cap < oldLen+1:
|
||||||
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, 1, sizeof(T)))
|
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, 1, sizeof(T)))
|
||||||
xu.len = oldLen+1
|
xu.len = oldLen+1
|
||||||
|
# .nodestroy means `xu.p.data[oldLen] = value` is compiled into a
|
||||||
|
# copyMem(). This is fine as know by construction that
|
||||||
|
# in `xu.p.data[oldLen]` there is nothing to destroy.
|
||||||
|
# We also save the `wasMoved + destroy` pair for the sink parameter.
|
||||||
xu.p.data[oldLen] = value
|
xu.p.data[oldLen] = value
|
||||||
|
|
||||||
proc setLen[T](s: var seq[T], newlen: Natural) =
|
proc setLen[T](s: var seq[T], newlen: Natural) =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue