mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-13 06:43:52 +00:00
@@ -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
|
||||
|
||||
@@ -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)
|
||||
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: int32; nifName: string): NifIndexEntry =
|
||||
assert module < 0'i32
|
||||
let index = idToIdx(module)
|
||||
let ii = addr c.mods[index].index
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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..<n.len:
|
||||
if len(n[i]) == 0: continue
|
||||
if n[i][0].kind != nkPragmaExpr: continue
|
||||
for p in 0..<n[i][0].len:
|
||||
if (n[i][0][p].kind notin {nkSym, nkPostfix}): continue
|
||||
var s = n[i][0][p]
|
||||
if s.kind == nkPostfix:
|
||||
s = n[i][0][p][1]
|
||||
if {sfExportc, sfCompilerProc} * s.sym.flags == {sfExportc}:
|
||||
discard getTypeDescAux(m, s.typ, intSet, descKindFromSymKind(s.sym.kind))
|
||||
if m.g.generatedHeader != nil:
|
||||
discard getTypeDescAux(m.g.generatedHeader, s.typ, intSet, descKindFromSymKind(s.sym.kind))
|
||||
let compress = optCompress in m.config.globalOptions
|
||||
for typedef in n:
|
||||
let s = retrieveSym(typedef)
|
||||
if s != nil and ({sfExportc, sfCompilerProc} * s.flags == {sfExportc} or compress) and s.typ != nil and
|
||||
not containsGenericType(s.typ) and
|
||||
s.typ.kind notin {tyVoid, tyNot, tyAnything, tyOr, tyAnd, tyUntyped, tyTyped, tyNone, tyNil, tySink}:
|
||||
discard getTypeDescAux(m, s.typ, intSet, descKindFromSymKind(s.kind))
|
||||
if m.g.generatedHeader != nil:
|
||||
discard getTypeDescAux(m.g.generatedHeader, s.typ, intSet, descKindFromSymKind(s.kind))
|
||||
|
||||
@@ -63,7 +63,7 @@ proc addForwardedProc(m: BModule, prc: PSym) =
|
||||
|
||||
proc findPendingModule(m: BModule, s: PSym): BModule =
|
||||
# TODO fixme
|
||||
if m.config.symbolFiles == v2Sf:
|
||||
if m.config.symbolFiles == v2Sf or optCompress in m.config.globalOptions:
|
||||
let ms = s.itemId.module #getModule(s)
|
||||
result = m.g.modules[ms]
|
||||
else:
|
||||
@@ -506,7 +506,7 @@ include ccgreset
|
||||
proc resetLoc(p: BProc, loc: var TLoc) =
|
||||
let containsGcRef = optSeqDestructors notin p.config.globalOptions and containsGarbageCollectedRef(loc.t)
|
||||
let typ = skipTypes(loc.t, abstractVarRange)
|
||||
if isImportedCppType(typ):
|
||||
if isImportedCppType(typ):
|
||||
var didGenTemp = false
|
||||
let rl = rdLoc(loc)
|
||||
let init = genCppInitializer(p.module, p, typ, didGenTemp)
|
||||
@@ -600,7 +600,7 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
|
||||
# ``var v = X()`` gets transformed into ``X(&v)``.
|
||||
# Nowadays the logic in ccgcalls deals with this case however.
|
||||
if not immediateAsgn:
|
||||
ensureMutable v
|
||||
backendEnsureMutable v
|
||||
constructLoc(p, v.locImpl)
|
||||
|
||||
proc getTemp(p: BProc, t: PType, needsInit=false): TLoc =
|
||||
@@ -785,7 +785,7 @@ proc fillProcLoc(m: BModule; n: PNode) =
|
||||
let sym = n.sym
|
||||
if sym.loc.k == locNone:
|
||||
fillBackendName(m, sym)
|
||||
ensureMutable sym
|
||||
backendEnsureMutable sym
|
||||
fillLoc(sym.locImpl, locProc, n, OnStack)
|
||||
|
||||
proc getLabel(p: BProc): TLabel =
|
||||
@@ -1362,7 +1362,8 @@ proc genProcAux*(m: BModule, prc: PSym) =
|
||||
closureSetup(p, prc)
|
||||
genProcBody(p, procBody)
|
||||
|
||||
prc.info = tmpInfo
|
||||
# IC: spurious write, seems fine for now:
|
||||
prc.infoImpl = tmpInfo
|
||||
|
||||
var generatedProc = newBuilder("")
|
||||
generatedProc.genCLineDir prc.info, m.config
|
||||
@@ -1445,6 +1446,8 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||
getModuleDllPath(m, sym),
|
||||
'"' & name & '"')
|
||||
elif not containsOrIncl(m.declaredProtos, sym.id):
|
||||
if optCompress in m.config.globalOptions:
|
||||
m.queue.add(sym)
|
||||
let asPtr = isReloadable(m, sym)
|
||||
var header = newBuilder("")
|
||||
var visibility: DeclVisibility = None
|
||||
@@ -1464,6 +1467,8 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||
m.s[cfsProcHeaders].add(extract(header))
|
||||
m.s[cfsProcHeaders].finishProcHeaderAsProto()
|
||||
|
||||
include inliner
|
||||
|
||||
# TODO: figure out how to rename this - it DOES generate a forward declaration
|
||||
proc genProcNoForward(m: BModule, prc: PSym) =
|
||||
if lfImportCompilerProc in prc.loc.flags:
|
||||
@@ -1502,16 +1507,22 @@ proc genProcNoForward(m: BModule, prc: PSym) =
|
||||
#if prc.loc.k == locNone:
|
||||
# mangle the inline proc based on the module where it is defined -
|
||||
# not on the first module that uses it
|
||||
let m2 = if m.config.symbolFiles != disabledSf: m
|
||||
else: findPendingModule(m, prc)
|
||||
fillProcLoc(m2, prc.ast[namePos])
|
||||
#elif {sfExportc, sfImportc} * prc.flags == {}:
|
||||
# # reset name to restore consistency in case of hashing collisions:
|
||||
# echo "resetting ", prc.id, " by ", m.module.name.s
|
||||
# prc.loc.snippet = nil
|
||||
# prc.loc.snippet = mangleName(m, prc)
|
||||
genProcPrototype(m, prc)
|
||||
genProcAux(m, prc)
|
||||
if m.module.itemId.module != prc.itemId.module and optCompress in m.config.globalOptions:
|
||||
let prcCopy = copyInlineProc(prc, m.idgen)
|
||||
fillProcLoc(m, prcCopy.ast[namePos])
|
||||
genProcPrototype(m, prcCopy)
|
||||
genProcAux(m, prcCopy)
|
||||
else:
|
||||
let m2 = if m.config.symbolFiles != disabledSf: m
|
||||
else: findPendingModule(m, prc)
|
||||
fillProcLoc(m2, prc.ast[namePos])
|
||||
#elif {sfExportc, sfImportc} * prc.flags == {}:
|
||||
# # reset name to restore consistency in case of hashing collisions:
|
||||
# echo "resetting ", prc.id, " by ", m.module.name.s
|
||||
# prc.loc.snippet = nil
|
||||
# prc.loc.snippet = mangleName(m, prc)
|
||||
genProcPrototype(m, prc)
|
||||
genProcAux(m, prc)
|
||||
elif sfImportc notin prc.flags:
|
||||
var q = findPendingModule(m, prc)
|
||||
fillProcLoc(q, prc.ast[namePos])
|
||||
@@ -1571,7 +1582,7 @@ proc genVarPrototype(m: BModule, n: PNode) =
|
||||
let sym = n.sym
|
||||
useHeader(m, sym)
|
||||
fillBackendName(m, sym)
|
||||
ensureMutable sym
|
||||
backendEnsureMutable sym
|
||||
fillLoc(sym.locImpl, locGlobalVar, n, OnHeap)
|
||||
if treatGlobalDifferentlyForHCR(m, sym): incl(sym, lfIndirect)
|
||||
|
||||
@@ -2509,6 +2520,11 @@ proc writeModule(m: BModule, pending: bool) =
|
||||
let cfile = getCFile(m)
|
||||
if moduleHasChanged(m.g.graph, m.module):
|
||||
genInitCode(m)
|
||||
|
||||
while m.queue.len > 0:
|
||||
let sym = m.queue.pop()
|
||||
genProcAux(m, sym)
|
||||
|
||||
finishTypeDescriptions(m)
|
||||
if sfMainModule in m.module.flags:
|
||||
# generate main file:
|
||||
|
||||
@@ -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
|
||||
|
||||
122
compiler/inliner.nim
Normal file
122
compiler/inliner.nim
Normal file
@@ -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..<n.len:
|
||||
result[i] = copySymdef(n[i], locals, idgen, owner)
|
||||
|
||||
proc copyInlineProcBody(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 sym = locals.getOrDefault(n.sym.id)
|
||||
if sym != nil:
|
||||
result = newSymNode(sym, n.info)
|
||||
else:
|
||||
result = n
|
||||
of nkLetSection, nkVarSection:
|
||||
result = shallowCopy(n)
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
if it.kind == nkCommentStmt:
|
||||
result[i] = it
|
||||
elif it.kind in {nkIdentDefs, nkConstDef}:
|
||||
result[i] = shallowCopy(it)
|
||||
for j in 0..<it.len-2:
|
||||
result[i][j] = copySymdef(it[j], locals, idgen, owner)
|
||||
for j in it.len-2..<it.len:
|
||||
result[i][j] = copyInlineProcBody(it[j], locals, idgen, owner)
|
||||
else:
|
||||
assert it.kind == nkVarTuple
|
||||
result[i] = shallowCopy(it)
|
||||
for j in 0..<it.len-2:
|
||||
assert it[j].kind == nkSym
|
||||
let oldSym = it[j].sym
|
||||
let newSym = copySym(oldSym, idgen)
|
||||
setOwner(newSym, owner)
|
||||
locals[oldSym.id] = newSym
|
||||
result[i][j] = newSymNode(newSym, oldSym.info)
|
||||
for j in it.len-2..<it.len:
|
||||
result[i][j] = copyInlineProcBody(it[j], locals, idgen, owner)
|
||||
|
||||
of nkForStmt, nkParForStmt:
|
||||
result = shallowCopy(n)
|
||||
for i in 0..<n.len-2:
|
||||
assert n[i].kind == nkSym
|
||||
let oldSym = n[i].sym
|
||||
let newSym = copySym(oldSym, idgen)
|
||||
setOwner(newSym, owner)
|
||||
locals[oldSym.id] = newSym
|
||||
result[i] = newSymNode(newSym, oldSym.info)
|
||||
result[n.len-2] = copyInlineProcBody(n[n.len-2], locals, idgen, owner)
|
||||
result[n.len-1] = copyInlineProcBody(n[n.len-1], locals, idgen, owner)
|
||||
of routineDefs, nkTypeSection, nkTypeOfExpr, nkMixinStmt, nkBindStmt, nkConstSection:
|
||||
result = n
|
||||
else:
|
||||
result = shallowCopy(n)
|
||||
for i in 0..<n.len:
|
||||
result[i] = copyInlineProcBody(n[i], locals, idgen, owner)
|
||||
|
||||
proc copyParams(n: PNode; locals: var Table[int, PSym]; idgen: IdGenerator; owner: PSym): PNode =
|
||||
result = shallowCopy(n)
|
||||
result[0] = n[0] # return type
|
||||
for i in 1..<n.len:
|
||||
let it = n[i]
|
||||
assert it.kind == nkIdentDefs
|
||||
result[i] = shallowCopy(it)
|
||||
for j in 0..<it.len-2:
|
||||
assert it[j].kind == nkSym
|
||||
let oldSym = it[j].sym
|
||||
let newSym = copySym(oldSym, idgen)
|
||||
setOwner(newSym, owner)
|
||||
locals[oldSym.id] = newSym
|
||||
result[i][j] = newSymNode(newSym, oldSym.info)
|
||||
owner.typ.addParam newSym
|
||||
for j in it.len-2..<it.len:
|
||||
result[i][j] = copyInlineProcBody(it[j], locals, idgen, owner)
|
||||
|
||||
proc copyInlineProc(prc: PSym; idgen: IdGenerator): PSym =
|
||||
result = copySym(prc, idgen)
|
||||
var locals = initTable[int, PSym]()
|
||||
|
||||
var a = shallowCopy(prc.ast)
|
||||
if resultPos < prc.ast.len and prc.ast[resultPos].kind == nkSym:
|
||||
let oldRes = prc.ast[resultPos].sym
|
||||
let newRes = copySym(oldRes, idgen)
|
||||
setOwner(newRes, result)
|
||||
locals[oldRes.id] = newRes
|
||||
a[resultPos] = newSymNode(newRes, oldRes.info)
|
||||
|
||||
result.typ = copyType(prc.typ, idgen, result)
|
||||
result.typ.n = newNodeI(prc.typ.n.kind, prc.typ.n.info)
|
||||
if prc.typ.n.len > 0:
|
||||
result.typ.n.add copyNode(prc.typ.n[0])
|
||||
for i in 1..<prc.typ.n.len:
|
||||
let it = prc.typ.n[i]
|
||||
assert it.kind == nkSym
|
||||
let oldSym = it.sym
|
||||
let newSym = copySym(oldSym, idgen)
|
||||
setOwner(newSym, result)
|
||||
locals[oldSym.id] = newSym
|
||||
result.typ.addParam newSym
|
||||
|
||||
for i in 0..<prc.ast.len:
|
||||
if i == paramsPos:
|
||||
a[i] = copyTree(prc.ast[i])
|
||||
elif i == resultPos and prc.ast[i].kind == nkSym:
|
||||
discard "handled above"
|
||||
else:
|
||||
a[i] = copyInlineProcBody(prc.ast[i], locals, idgen, result)
|
||||
result.ast = a
|
||||
|
||||
#echo "Produced: ", renderTree(result.ast, {renderIds})
|
||||
@@ -133,6 +133,16 @@ proc fileInfoIdx*(conf: ConfigRef; filename: RelativeFile): FileIndex =
|
||||
var dummy: bool = false
|
||||
fileInfoIdx(conf, AbsoluteFile expandFilename(filename.string), dummy)
|
||||
|
||||
proc registerNifSuffix*(conf: ConfigRef; suffix: string; isKnownFile: var bool): FileIndex =
|
||||
result = conf.m.filenameToIndexTbl.getOrDefault(suffix, InvalidFileIdx)
|
||||
if result == InvalidFileIdx:
|
||||
isKnownFile = false
|
||||
result = conf.m.fileInfos.len.FileIndex
|
||||
conf.m.fileInfos.add(newFileInfo(AbsoluteFile suffix, RelativeFile suffix))
|
||||
conf.m.filenameToIndexTbl[suffix] = result
|
||||
else:
|
||||
isKnownFile = true
|
||||
|
||||
proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =
|
||||
result = TLineInfo(fileIndex: fileInfoIdx)
|
||||
if line < int high(uint16):
|
||||
|
||||
@@ -372,9 +372,9 @@ proc useVarNoInitCheck(a: PEffects; n: PNode; s: PSym) =
|
||||
|
||||
proc useVar(a: PEffects, n: PNode) =
|
||||
let s = n.sym
|
||||
if a.inExceptOrFinallyStmt > 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.}
|
||||
|
||||
@@ -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)):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user