diff --git a/compiler/ast.nim b/compiler/ast.nim index 50bcad75648d..7ae2f67765d2 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -57,6 +57,16 @@ proc ensureMutable*(t: PType) {.inline.} = assert t.state != Sealed if t.state == Partial: loadType(t) +proc backendEnsureMutable*(s: PSym) {.inline.} = + #assert s.state != Sealed + # ^ IC review this later + if s.state == Partial: loadSym(s) + +proc backendEnsureMutable*(t: PType) {.inline.} = + #assert t.state != Sealed + # ^ IC review this later + if t.state == Partial: loadType(t) + proc owner*(s: PSym): PSym {.inline.} = if s.state == Partial: loadSym(s) result = s.ownerFieldImpl diff --git a/compiler/ast2nif.nim b/compiler/ast2nif.nim index af4955d94739..dbf388e9d6a8 100644 --- a/compiler/ast2nif.nim +++ b/compiler/ast2nif.nim @@ -13,7 +13,7 @@ import std / [assertions, tables, sets] from std / strutils import startsWith import astdef, idents, msgs, options import lineinfos as astli -import pathutils +import pathutils #, modulegraphs import "../dist/nimony/src/lib" / [bitabs, nifstreams, nifcursors, lineinfos, nifindexes, nifreader] import "../dist/nimony/src/gear2" / modnames @@ -258,6 +258,10 @@ proc writeLib(w: var Writer; dest: var TokenBuf; lib: PLib) = proc writeSymDef(w: var Writer; dest: var TokenBuf; sym: PSym) = dest.addParLe sdefTag, trLineInfo(w, sym.infoImpl) dest.addSymDef pool.syms.getOrIncl(w.toNifSymName(sym)), NoLineInfo + if sfExported in sym.flagsImpl: + dest.addIdent "x" + else: + dest.addDotToken if sym.magicImpl == mNone: dest.addDotToken else: @@ -352,14 +356,14 @@ proc trInclude(w: var Writer; n: PNode) = w.deps.addParRi proc trImport(w: var Writer; n: PNode) = - w.deps.addParLe pool.tags.getOrIncl(toNifTag(n.kind)), trLineInfo(w, n.info) for child in n: - assert child.kind == nkSym - let s = child.sym - assert s.kindImpl == skModule - let fp = toFullPath(w.infos.config, s.positionImpl.FileIndex) - w.deps.addStrLit fp - w.deps.addParRi + if child.kind == nkSym: + w.deps.addParLe pool.tags.getOrIncl(toNifTag(n.kind)), trLineInfo(w, n.info) + let s = child.sym + assert s.kindImpl == skModule + let fp = toFullPath(w.infos.config, s.positionImpl.FileIndex) + w.deps.addStrLit fp + w.deps.addParRi proc writeNode(w: var Writer; dest: var TokenBuf; n: PNode) = if n == nil: @@ -421,6 +425,7 @@ proc writeNode(w: var Writer; dest: var TokenBuf; n: PNode) = var ast = n if n[namePos].kind == nkSym: ast = n[namePos].sym.astImpl + if ast == nil: ast = n w.withNode dest, ast: # Process body and other parts for i in 0 ..< ast.len: @@ -463,7 +468,8 @@ proc writeNifModule*(config: ConfigRef; thisModule: int32; n: PNode) = inner.addParRi() let m = modname(w.moduleToNifSuffix, w.currentModule, w.infos.config) - let d = toGeneratedFile(config, AbsoluteFile(m), ".nif").string + let nifFilename = AbsoluteFile(m).changeFileExt(".nif") + let d = completeGeneratedFilePath(config, nifFilename).string var dest = createTokenBuf(600) dest.addParLe pool.tags.getOrIncl(toNifTag(nkStmtList)), rootInfo @@ -472,7 +478,8 @@ proc writeNifModule*(config: ConfigRef; thisModule: int32; n: PNode) = dest.add inner dest.addParRi() - writeFileAndIndex d, dest + writeFile(dest, d) + createIndex(d, false, dest[0].info) # --------------------------- Loader (lazy!) ----------------------------------------------- @@ -536,48 +543,37 @@ type DecodeContext* = object infos: LineInfoWriter - moduleIds: Table[string, int32] + #moduleIds: Table[string, int32] types: Table[ItemId, (PType, NifIndexEntry)] syms: Table[ItemId, (PSym, NifIndexEntry)] mods: seq[NifModule] cache: IdentCache - moduleToNifSuffix: Table[FileIndex, string] + #moduleToNifSuffix: Table[FileIndex, string] proc createDecodeContext*(config: ConfigRef; cache: IdentCache): DecodeContext = ## Supposed to be a global variable result = DecodeContext(infos: LineInfoWriter(config: config), cache: cache) -proc idToIdx(x: int32): int {.inline.} = - assert x <= -2'i32 - result = -(x+2) - -proc cursorFromIndexEntry(c: var DecodeContext; module: int32; entry: NifIndexEntry; +proc cursorFromIndexEntry(c: var DecodeContext; module: FileIndex; entry: NifIndexEntry; buf: var TokenBuf): Cursor = - let m = idToIdx(module) - let s = addr c.mods[m].stream + let s = addr c.mods[module.int32].stream s.r.jumpTo entry.offset var buf = createTokenBuf(30) nifcursors.parse(s[], buf, entry.info) result = cursorAt(buf, 0) -proc moduleId(c: var DecodeContext; suffix: string): int32 = - # We don't know the "real" FileIndex due to our mapping to a short "Module suffix" - # This is not a problem, we use negative `ItemId.module` values here and then - # there is no interference with in-memory-modules. Modulegraphs.nim already uses -1 - # so we start at -2 here. - result = c.moduleIds.getOrDefault(suffix) - if result == 0: - result = -int32(c.moduleIds.len + 2) # negative index! +proc moduleId(c: var DecodeContext; suffix: string): FileIndex = + var isKnownFile = false + result = c.infos.config.registerNifSuffix(suffix, isKnownFile) + if not isKnownFile: let modFile = (getNimcacheDir(c.infos.config) / RelativeFile(suffix & ".nif")).string let idxFile = (getNimcacheDir(c.infos.config) / RelativeFile(suffix & ".idx.nif")).string - c.moduleIds[suffix] = result - c.mods.add NifModule(stream: nifstreams.open(modFile), index: readIndex(idxFile)) - assert c.mods.len-1 == idToIdx(result) - -proc getOffset(c: var DecodeContext; module: int32; nifName: string): NifIndexEntry = - assert module < 0'i32 - let index = idToIdx(module) - let ii = addr c.mods[index].index + if result.int >= c.mods.len: + c.mods.setLen(result.int + 1) + c.mods[result.int] = NifModule(stream: nifstreams.open(modFile), index: readIndex(idxFile)) + +proc getOffset(c: var DecodeContext; module: FileIndex; nifName: string): NifIndexEntry = + let ii = addr c.mods[module.int32].index result = ii.public.getOrDefault(nifName) if result.offset == 0: result = ii.private.getOrDefault(nifName) @@ -601,10 +597,10 @@ proc loadTypeStub(c: var DecodeContext; t: SymId): PType = inc i if i < name.len and name[i] == '.': inc i let suffix = name.substr(i) - let id = ItemId(module: moduleId(c, suffix), item: itemId) + let id = ItemId(module: moduleId(c, suffix).int32, item: itemId) result = c.types.getOrDefault(id)[0] if result == nil: - let offs = c.getOffset(id.module, name) + let offs = c.getOffset(id.module.FileIndex, name) result = PType(itemId: id, uniqueId: id, kind: TTypeKind(k), state: Partial) c.types[id] = (result, offs) @@ -627,10 +623,10 @@ proc loadSymStub(c: var DecodeContext; t: SymId): PSym = let symAsStr = pool.syms[t] let sn = parseSymName(symAsStr) let module = moduleId(c, sn.module) - let val = addr c.mods[idToIdx(module)].symCounter + let val = addr c.mods[module.int32].symCounter inc val[] - let id = ItemId(module: module, item: val[]) + let id = ItemId(module: module.int32, item: val[]) result = c.syms.getOrDefault(id)[0] if result == nil: let offs = c.getOffset(module, symAsStr) @@ -696,7 +692,7 @@ proc loadType*(c: var DecodeContext; t: PType) = if t.state != Partial: return t.state = Sealed var buf = createTokenBuf(30) - var n = cursorFromIndexEntry(c, t.itemId.module, c.types[t.itemId][1], buf) + var n = cursorFromIndexEntry(c, t.itemId.module.FileIndex, c.types[t.itemId][1], buf) expect n, ParLe if n.tagId != tdefTag: @@ -745,7 +741,7 @@ proc loadSym*(c: var DecodeContext; s: PSym) = if s.state != Partial: return s.state = Sealed var buf = createTokenBuf(30) - var n = cursorFromIndexEntry(c, s.itemId.module, c.syms[s.itemId][1], buf) + var n = cursorFromIndexEntry(c, s.itemId.module.FileIndex, c.syms[s.itemId][1], buf) expect n, ParLe if n.tagId != sdefTag: @@ -754,6 +750,17 @@ proc loadSym*(c: var DecodeContext; s: PSym) = expect n, SymbolDef # ignore the symbol's name, we have already used it to create this PSym instance! inc n + if n.kind == Ident: + if pool.strings[n.litId] == "x": + s.flagsImpl.incl sfExported + inc n + else: + raiseAssert "expected `x` as the export marker" + elif n.kind == DotToken: + inc n + else: + raiseAssert "expected `x` or '.' but got " & $n.kind + loadField s.magicImpl loadField s.flagsImpl loadField s.optionsImpl @@ -894,20 +901,20 @@ proc loadNode(c: var DecodeContext; n: var Cursor): PNode = else: raiseAssert "Not yet implemented " & $n.kind - -proc loadNifModule*(c: var DecodeContext; f: FileIndex): PNode = - let moduleSuffix = modname(c.moduleToNifSuffix, f.int, c.infos.config) - let modFile = toGeneratedFile(c.infos.config, AbsoluteFile(moduleSuffix), ".nif").string - - var buf = createTokenBuf(300) - var s = nifstreams.open(modFile) - # XXX We can optimize this here and only load the top level entries! - try: - nifcursors.parse(s, buf, NoLineInfo) - finally: - nifstreams.close(s) - var n = cursorAt(buf, 0) - result = loadNode(c, n) +when false: + proc loadNifModule*(c: var DecodeContext; f: FileIndex): PNode = + let moduleSuffix = moduleSuffix(c.infos.config, f) + let modFile = toGeneratedFile(c.infos.config, AbsoluteFile(moduleSuffix), ".nif").string + + var buf = createTokenBuf(300) + var s = nifstreams.open(modFile) + # XXX We can optimize this here and only load the top level entries! + try: + nifcursors.parse(s, buf, NoLineInfo) + finally: + nifstreams.close(s) + var n = cursorAt(buf, 0) + result = loadNode(c, n) when isMainModule: import std / syncio diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 6b2a64409967..b5ece69ae643 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -170,7 +170,7 @@ proc canMove(p: BProc, n: PNode; dest: TLoc): bool = template simpleAsgn(builder: var Builder, dest, src: TLoc) = let rd = rdLoc(dest) let rs = rdLoc(src) - builder.addAssignment(rd, rs) + builder.addAssignment(rd, rs) proc genRefAssign(p: BProc, dest, src: TLoc) = if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config): @@ -675,7 +675,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = if e[2].kind in {nkIntLit..nkInt64Lit}: needsOverflowCheck = e[2].intVal == -1 if canBeZero: - # remove extra paren from `==` op here to avoid Wparentheses-equality: + # remove extra paren from `==` op here to avoid Wparentheses-equality: p.s(cpsStmts).addSingleIfStmt(removeSinglePar(cOp(Equal, rdLoc(b), cIntValue(0)))): p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseDivByZero")) raiseInstr(p, p.s(cpsStmts)) @@ -696,7 +696,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = let ra = rdLoc(a) if optOverflowCheck in p.options: let first = cIntLiteral(firstOrd(p.config, t)) - # remove extra paren from `==` op here to avoid Wparentheses-equality: + # remove extra paren from `==` op here to avoid Wparentheses-equality: p.s(cpsStmts).addSingleIfStmt(removeSinglePar(cOp(Equal, ra, first))): p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseOverflow")) raiseInstr(p, p.s(cpsStmts)) @@ -3435,7 +3435,7 @@ proc genConstDefinition(q: BModule; p: BProc; sym: PSym) = proc genConstStmt(p: BProc, n: PNode) = # This code is only used in the new DCE implementation. - assert useAliveDataFromDce in p.module.flags + assert delayedCodegen(p.module) let m = p.module for it in n: if it[0].kind == nkSym: @@ -3453,7 +3453,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = var sym = n.sym case sym.kind of skMethod: - if useAliveDataFromDce in p.module.flags or {sfDispatcher, sfForward} * sym.flags != {}: + if delayedCodegen(p.module) or {sfDispatcher, sfForward} * sym.flags != {}: # we cannot produce code for the dispatcher yet: fillProcLoc(p.module, n) genProcPrototype(p.module, sym) @@ -3466,7 +3466,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = if sfCompileTime in sym.flags: localError(p.config, n.info, "request to generate code for .compileTime proc: " & sym.name.s) - if useAliveDataFromDce in p.module.flags and sym.typ.callConv != ccInline: + if delayedCodegen(p.module) and sym.typ.callConv != ccInline: fillProcLoc(p.module, n) genProcPrototype(p.module, sym) else: @@ -3479,7 +3479,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = var lit = newBuilder("") genLiteral(p, sym.astdef, sym.typ, lit) putIntoDest(p, d, n, extract(lit), OnStatic) - elif useAliveDataFromDce in p.module.flags: + elif delayedCodegen(p.module): genConstHeader(p.module, p.module, p, sym) assert((sym.loc.snippet != "") and (sym.loc.t != nil)) putLocIntoDest(p, d, sym.loc) @@ -3611,7 +3611,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of nkWhileStmt: genWhileStmt(p, n) of nkVarSection, nkLetSection: genVarStmt(p, n) of nkConstSection: - if useAliveDataFromDce in p.module.flags: + if delayedCodegen(p.module): genConstStmt(p, n) else: # enforce addressable consts for exportc let m = p.module @@ -3677,7 +3677,10 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef: if n[genericParamsPos].kind == nkEmpty: var prc = n[namePos].sym - if useAliveDataFromDce in p.module.flags: + if optCompress in p.config.globalOptions: + if prc.magic in generatedMagics: + genProc(p.module, prc) + elif delayedCodegen(p.module): if p.module.alive.contains(prc.itemId.item) and prc.magic in generatedMagics: genProc(p.module, prc) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 15fb55c3464b..4302b3058fdd 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -366,6 +366,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) = if v.flags * {sfImportc, sfExportc} == {sfImportc} and value.kind == nkEmpty and v.loc.flags * {lfHeader, lfNoDecl} != {}: + # IC XXX: this is bad, we should set v.loc regardless here return if sfPure in v.flags: # v.owner.kind != skModule: @@ -461,7 +462,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) = if value.kind != nkEmpty and valueAsRope.len == 0: genLineDir(targetProc, vn) if not isCppCtorCall: - ensureMutable v + backendEnsureMutable v loadInto(targetProc, vn, value, v.locImpl) if forHcr: endBlockWith(targetProc): diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index eb81c4e56286..545274b125ec 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -108,7 +108,7 @@ proc fillParamName(m: BModule; s: PSym) = # and a function called in main or proxy uses `socket` as a parameter name. # That would lead to either needing to reload `proxy` or to overwrite the # executable file for the main module, which is running (or both!) -> error. - ensureMutable s + backendEnsureMutable s s.locImpl.snippet = res.rope proc fillLocalName(p: BProc; s: PSym) = @@ -158,8 +158,8 @@ proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope = else: break let typ = if typ.kind in {tyAlias, tySink, tyOwned}: typ.elementType else: typ - ensureMutable typ if typ.loc.snippet == "": + backendEnsureMutable typ typ.typeName(typ.locImpl.snippet) typ.locImpl.snippet.add $sig else: @@ -608,7 +608,7 @@ proc genProcParams(m: BModule; t: PType, rettype: var Rope, params: var Builder, else: descKind = dkRefParam if isCompileTimeOnly(param.typ): continue - ensureMutable param + backendEnsureMutable param fillParamName(m, param) fillLoc(param.locImpl, locParam, t.n[i], param.paramStorageLoc) @@ -715,7 +715,7 @@ proc genRecordFieldsAux(m: BModule; n: PNode, if field.typ.kind == tyVoid: return #assert(field.ast == nil) let sname = mangleRecFieldName(m, field) - ensureMutable field + backendEnsureMutable field fillLoc(field.locImpl, locField, n, unionPrefix & sname, OnUnknown) # for importcpp'ed objects, we only need to set field.loc, but don't # have to recurse via 'getTypeDescAux'. And not doing so prevents problems @@ -1212,7 +1212,7 @@ proc genProcHeader(m: BModule; prc: PSym; result: var Builder; visibility: var D # using static is needed for inline procs var check = initIntSet() fillBackendName(m, prc) - ensureMutable prc + backendEnsureMutable prc fillLoc(prc.locImpl, locProc, prc.ast[namePos], OnUnknown) var rettype: Snippet = "" var desc = newBuilder("") @@ -2054,17 +2054,21 @@ proc genTypeInfo*(config: ConfigRef, m: BModule; t: PType; info: TLineInfo): Rop else: result = genTypeInfoV1(m, t, info) +proc retrieveSym(n: PNode): PSym = + case n.kind + of nkPostfix: result = retrieveSym(n[1]) + of nkPragmaExpr, nkTypeDef: result = retrieveSym(n[0]) + of nkSym: result = n.sym + else: result = nil + proc genTypeSection(m: BModule, n: PNode) = var intSet = initIntSet() - for i in 0.. 0: + let sym = m.queue.pop() + genProcAux(m, sym) + finishTypeDescriptions(m) if sfMainModule in m.module.flags: # generate main file: diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index f9ed9c6fdae9..479babb0b969 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -119,7 +119,7 @@ type mapping*: Rope # the generated mapping file (if requested) modules*: seq[BModule] # list of all compiled modules modulesClosed*: seq[BModule] # list of the same compiled modules, but in the order they were closed - forwardedProcs*: seq[PSym] # proc:s that did not yet have a body + forwardedProcs*: seq[PSym] # procs that did not yet have a body generatedHeader*: BModule typeInfoMarker*: TypeCacheWithOwner typeInfoMarkerV2*: TypeCacheWithOwner @@ -155,6 +155,7 @@ type forwTypeCache*: TypeCache # cache for forward declarations of types declaredThings*: IntSet # things we have declared in this .c file declaredProtos*: IntSet # prototypes we have declared in this .c file + queue*: seq[PSym] # queue of procs to generate alive*: IntSet # symbol IDs of alive data as computed by `dce.nim` headerFiles*: seq[string] # needed headers to include typeInfoMarker*: TypeCache # needed for generating type information @@ -178,6 +179,9 @@ template config*(m: BModule): ConfigRef = m.g.config template config*(p: BProc): ConfigRef = p.module.g.config template vccAndC*(p: BProc): bool = p.module.config.cCompiler == ccVcc and p.module.config.backend == backendC +proc delayedCodegen*(m: BModule): bool {.inline.} = + useAliveDataFromDce in m.flags or m.config.globalOptions.contains(optCompress) + proc includeHeader*(this: BModule; header: string) = if not this.headerFiles.contains header: this.headerFiles.add header diff --git a/compiler/inliner.nim b/compiler/inliner.nim new file mode 100644 index 000000000000..a8f032bccc4f --- /dev/null +++ b/compiler/inliner.nim @@ -0,0 +1,122 @@ + +proc copySymdef(n: PNode; locals: var Table[int, PSym]; idgen: IdGenerator; owner: PSym): PNode = + case n.kind + of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: + result = n + of nkSym: + let oldSym = n.sym + let newSym = copySym(oldSym, idgen) + setOwner(newSym, owner) + locals[oldSym.id] = newSym + result = newSymNode(newSym, oldSym.info) + else: + result = shallowCopy(n) + for i in 0.. 0: + result.typ.n.add copyNode(prc.typ.n[0]) + for i in 1.. 0: - incl s, sfUsedInFinallyOrExcept if isLocalSym(a, s): + if a.inExceptOrFinallyStmt > 0: + incl s, sfUsedInFinallyOrExcept if sfNoInit in s.flags: # If the variable is explicitly marked as .noinit. do not emit any error a.init.add s.id diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim index eb5bb29f049d..f7d89037e38e 100644 --- a/compiler/sighashes.nim +++ b/compiler/sighashes.nim @@ -143,15 +143,15 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]; conf: Confi if t.sym != nil and {sfImportc, sfExportc} * t.sym.flags != {}: c.hashSym(t.sym) of tyObject, tyEnum: - if t.typeInst != nil: + if t.typeInstImpl != nil: # prevent against infinite recursions here, see bug #8883: - let inst = t.typeInst - t.typeInst = nil + let inst = t.typeInstImpl + t.typeInstImpl = nil # IC: spurious writes are ok since we set it back immediately assert inst.kind == tyGenericInst c.hashType inst.genericHead, flags, conf for _, a in inst.genericInstParams: c.hashType a, flags, conf - t.typeInst = inst + t.typeInstImpl = inst return c &= char(t.kind) # Every cyclic type in Nim need to be constructed via some 't.sym', so this diff --git a/lib/std/private/digitsutils.nim b/lib/std/private/digitsutils.nim index b6d2d10b97a9..73b28a68ba8d 100644 --- a/lib/std/private/digitsutils.nim +++ b/lib/std/private/digitsutils.nim @@ -117,3 +117,5 @@ proc addInt*(result: var string; x: int64) {.enforceNoRaises.} = proc addInt*(result: var string; x: int) {.inline, enforceNoRaises.} = addInt(result, int64(x)) + +{.pop.} diff --git a/lib/system.nim b/lib/system.nim index 9ef8128c2d46..c7667cfba412 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -555,9 +555,6 @@ type when defined(nimIcIntegrityChecks): include "system/exceptions" -else: - import system/exceptions - export exceptions when defined(js) or defined(nimdoc): type @@ -1651,6 +1648,25 @@ when not defined(js) and defined(nimV2): vTable: UncheckedArray[pointer] # vtable for types PNimTypeV2 = ptr TNimTypeV2 +when notJSnotNims and defined(nimSeqsV2): + const nimStrVersion {.core.} = 2 + + type + NimStrPayloadBase = object + cap: int + + NimStrPayload {.core.} = object + cap: int + data: UncheckedArray[char] + + NimStringV2 {.core.} = object + len: int + p: ptr NimStrPayload ## can be nil if len == 0. + +when not defined(nimIcIntegrityChecks): + import system/exceptions + export exceptions + when notJSnotNims and defined(nimSeqsV2): include "system/strs_v2" include "system/seqs_v2" @@ -2248,6 +2264,37 @@ when not defined(js) and declared(alloc0) and declared(dealloc): inc(i) dealloc(a) +when notJSnotNims and hostOS != "standalone": + proc getCurrentException*(): ref Exception {.compilerRtl, inl, benign.} = + ## Retrieves the current exception; if there is none, `nil` is returned. + result = currException + + proc nimBorrowCurrentException(): ref Exception {.compilerRtl, inl, benign, nodestroy.} = + # .nodestroy here so that we do not produce a write barrier as the + # C codegen only uses it in a borrowed way: + result = currException + + proc getCurrentExceptionMsg*(): string {.inline, benign.} = + ## Retrieves the error message that was attached to the current + ## exception; if there is none, `""` is returned. + return if currException == nil: "" else: currException.msg + + proc setCurrentException*(exc: ref Exception) {.inline, benign.} = + ## Sets the current exception. + ## + ## .. warning:: Only use this if you know what you are doing. + currException = exc + + proc raiseDefect() {.compilerRtl.} = + let e = getCurrentException() + if e of Defect: + reportUnhandledError(e) + rawQuit(1) + +elif defined(nimscript): + proc getCurrentException*(): ref Exception {.compilerRtl.} = discard + proc raiseDefect*() {.compilerRtl.} = discard + when not defined(js): when hasThreadSupport: when hostOS != "standalone": @@ -2333,37 +2380,6 @@ when notJSnotNims and hasThreadSupport and hostOS != "standalone": include "system/channels_builtin" -when notJSnotNims and hostOS != "standalone": - proc getCurrentException*(): ref Exception {.compilerRtl, inl, benign.} = - ## Retrieves the current exception; if there is none, `nil` is returned. - result = currException - - proc nimBorrowCurrentException(): ref Exception {.compilerRtl, inl, benign, nodestroy.} = - # .nodestroy here so that we do not produce a write barrier as the - # C codegen only uses it in a borrowed way: - result = currException - - proc getCurrentExceptionMsg*(): string {.inline, benign.} = - ## Retrieves the error message that was attached to the current - ## exception; if there is none, `""` is returned. - return if currException == nil: "" else: currException.msg - - proc setCurrentException*(exc: ref Exception) {.inline, benign.} = - ## Sets the current exception. - ## - ## .. warning:: Only use this if you know what you are doing. - currException = exc - - proc raiseDefect() {.compilerRtl.} = - let e = getCurrentException() - if e of Defect: - reportUnhandledError(e) - rawQuit(1) - -elif defined(nimscript): - proc getCurrentException*(): ref Exception {.compilerRtl.} = discard - proc raiseDefect*() {.compilerRtl.} = discard - when notJSnotNims: {.push stackTrace: off, profiler: off.} when (defined(profiler) or defined(memProfiler)): diff --git a/lib/system/arc.nim b/lib/system/arc.nim index 5677013013d0..14da1531c28b 100644 --- a/lib/system/arc.nim +++ b/lib/system/arc.nim @@ -14,7 +14,7 @@ at offset 0 then. The ``ref`` object header is independent from the runtime type and only contains a reference count. ]# -{.push raises: [].} +{.push raises: [], rangeChecks: off.} when defined(gcOrc): const diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim index 1a7d7f0a9038..901f7a5f2b64 100644 --- a/lib/system/chcks.nim +++ b/lib/system/chcks.nim @@ -9,8 +9,6 @@ # Implementation of some runtime checks. include system/indexerrors -when defined(nimPreviewSlimSystem): - import std/formatfloat proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} = when hostOS == "standalone": @@ -53,12 +51,6 @@ proc raiseRangeErrorI(i, a, b: BiggestInt) {.compilerproc, noinline.} = else: sysFatal(RangeDefect, "value out of range: " & $i & " notin " & $a & " .. " & $b) -proc raiseRangeErrorF(i, a, b: float) {.compilerproc, noinline.} = - when defined(standalone): - sysFatal(RangeDefect, "value out of range") - else: - sysFatal(RangeDefect, "value out of range: " & $i & " notin " & $a & " .. " & $b) - proc raiseRangeErrorU(i, a, b: uint64) {.compilerproc, noinline.} = # todo: better error reporting sysFatal(RangeDefect, "value out of range") @@ -97,16 +89,6 @@ proc chckRangeU(i, a, b: uint64): uint64 {.compilerproc.} = result = 0 sysFatal(RangeDefect, "value out of range") -proc chckRangeF(x, a, b: float): float = - if x >= a and x <= b: - return x - else: - result = 0.0 - when hostOS == "standalone": - sysFatal(RangeDefect, "value out of range") - else: - sysFatal(RangeDefect, "value out of range: ", $x) - proc chckNil(p: pointer) = if p == nil: sysFatal(NilAccessDefect, "attempt to write to a nil address") @@ -164,3 +146,30 @@ when not defined(nimV2): when defined(nimV2): proc raiseObjectCaseTransition() {.compilerproc.} = sysFatal(FieldDefect, "assignment to discriminant changes object branch") + +import std/formatfloat + +when not defined(nimPreviewSlimSystem): + export addFloat + +func f2s(x: float | float32): string = + ## Outplace version of `addFloat`. + result = "" + result.addFloat(x) + + +proc raiseRangeErrorF(i, a, b: float) {.compilerproc, noinline.} = + when defined(standalone): + sysFatal(RangeDefect, "value out of range") + else: + sysFatal(RangeDefect, "value out of range: " & f2s(i) & " notin " & f2s(a) & " .. " & f2s(b)) + +proc chckRangeF(x, a, b: float): float = + if x >= a and x <= b: + return x + else: + result = 0.0 + when hostOS == "standalone": + sysFatal(RangeDefect, "value out of range") + else: + sysFatal(RangeDefect, "value out of range: ", f2s(x)) diff --git a/lib/system/strs_v2.nim b/lib/system/strs_v2.nim index 1bc8fb7d789c..9861c9ae4e43 100644 --- a/lib/system/strs_v2.nim +++ b/lib/system/strs_v2.nim @@ -9,20 +9,6 @@ ## Default new string implementation used by Nim's core. -type - NimStrPayloadBase = object - cap: int - - NimStrPayload {.core.} = object - cap: int - data: UncheckedArray[char] - - NimStringV2 {.core.} = object - len: int - p: ptr NimStrPayload ## can be nil if len == 0. - -const nimStrVersion {.core.} = 2 - {.push overflowChecks: off, rangeChecks: off.} template isLiteral(s): bool = (s.p == nil) or (s.p.cap and strlitFlag) == strlitFlag