Skip to content

Commit

Permalink
Merge branch 'devel' into pr_iterator_array_lent
Browse files Browse the repository at this point in the history
  • Loading branch information
ringabout authored Mar 5, 2024
2 parents 5918bdb + d373d30 commit 07dfc63
Show file tree
Hide file tree
Showing 63 changed files with 1,079 additions and 241 deletions.
7 changes: 5 additions & 2 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ slots when enlarging a sequence.
- Added `hasDefaultValue` to `std/typetraits` to check if a type has a valid default value.
- Added Viewport API for the JavaScript targets in the `dom` module.
- Added `toSinglyLinkedRing` and `toDoublyLinkedRing` to `std/lists` to convert from `openArray`s.
- ORC: To be enabled via `nimOrcStats` there is a new API called `GC_orcStats` that can be used to query how many
objects the cyclic collector did free. If the number is zero that is a strong indicator that you can use `--mm:arc`
instead of `--mm:orc`.

[//]: # "Deprecations:"

Expand All @@ -40,7 +43,7 @@ slots when enlarging a sequence.

## Language changes

- `noInit` can be used in types and fields to disable member initializers in the C++ backend.
- `noInit` can be used in types and fields to disable member initializers in the C++ backend.
- C++ custom constructors initializers see https://nim-lang.org/docs/manual_experimental.htm#constructor-initializer
- `member` can be used to attach a procedure to a C++ type.
- C++ `constructor` now reuses `result` instead creating `this`.
Expand All @@ -62,7 +65,7 @@ slots when enlarging a sequence.
symbols in generic routine bodies to be replaced by symbols injected locally
by templates/macros at instantiation time. `bind` may be used to keep the
captured symbols over the injected ones regardless of enabling the option.
Since this change may affect runtime behavior, the experimental switch
`genericsOpenSym` needs to be enabled, and a warning is given in the case
where an injected symbol would replace a captured symbol not bound by `bind`
Expand Down
2 changes: 1 addition & 1 deletion compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ type
tfIterator, # type is really an iterator, not a tyProc
tfPartial, # type is declared as 'partial'
tfNotNil, # type cannot be 'nil'
tfRequiresInit, # type constains a "not nil" constraint somewhere or
tfRequiresInit, # type contains a "not nil" constraint somewhere or
# a `requiresInit` field, so the default zero init
# is not appropriate
tfNeedsFullInit, # object type marked with {.requiresInit.}
Expand Down
6 changes: 3 additions & 3 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
if t.kind == tyInt64: prc64[m] else: prc[m])
putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res])
else:
let res = "($1)($2 $3 $4)" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
let res = "($1)(($2) $3 ($4))" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
putIntoDest(p, d, e, res)

proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
Expand Down Expand Up @@ -1857,9 +1857,9 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
if optBoundsCheck in p.options:
genBoundsCheck(p, m, b, c)
if op == mHigh:
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)", [rdLoc(b), rdLoc(c)]))
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1))", [rdLoc(b), rdLoc(c)]))
else:
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)+1", [rdLoc(b), rdLoc(c)]))
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1)+1)", [rdLoc(b), rdLoc(c)]))
else:
if not reifiedOpenArray(a):
if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)")
Expand Down
4 changes: 2 additions & 2 deletions compiler/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1037,8 +1037,8 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =

inc(p.labels, 2)
let etmp = p.labels

lineCg(p, cpsStmts, "std::exception_ptr T$1_;$n", [etmp])
#init on locals, fixes #23306
lineCg(p, cpsLocals, "std::exception_ptr T$1_;$n", [etmp])

let fin = if t[^1].kind == nkFinally: t[^1] else: nil
p.nestedTryStmts.add((fin, false, 0.Natural))
Expand Down
28 changes: 23 additions & 5 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,31 @@ proc mangleField(m: BModule; name: PIdent): string =
if isKeyword(name):
result.add "_0"

proc mangleProc(m: BModule; s: PSym; makeUnique: bool): string =
result = "_Z" # Common prefix in Itanium ABI
result.add encodeSym(m, s, makeUnique)
if s.typ.len > 1: #we dont care about the return param
for i in 1..<s.typ.len:
if s.typ[i].isNil: continue
result.add encodeType(m, s.typ[i])

if result in m.g.mangledPrcs:
result = mangleProc(m, s, true)
else:
m.g.mangledPrcs.incl(result)

proc fillBackendName(m: BModule; s: PSym) =
if s.loc.r == "":
var result = s.name.s.mangle.rope
result.add "__"
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
result.add "_u"
result.addInt s.itemId.item # s.disamb #
var result: Rope
if not m.compileToCpp and s.kind in routineKinds and optCDebug in m.g.config.globalOptions and
m.g.config.symbolFiles == disabledSf:
result = mangleProc(m, s, false).rope
else:
result = s.name.s.mangle.rope
result.add "__"
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
result.add "_u"
result.addInt s.itemId.item # s.disamb #
if m.hcrOn:
result.add '_'
result.add(idOrSig(s, m.module.name.s.mangle, m.sigConflicts, m.config))
Expand Down
65 changes: 62 additions & 3 deletions compiler/ccgutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import
ast, types, msgs, wordrecg,
platform, trees, options, cgendata

import std/[hashes, strutils]
import std/[hashes, strutils, formatfloat]

when defined(nimPreviewSlimSystem):
import std/assertions
Expand Down Expand Up @@ -126,10 +126,10 @@ proc mapSetType(conf: ConfigRef; typ: PType): TCTypeKind =
proc ccgIntroducedPtr*(conf: ConfigRef; s: PSym, retType: PType): bool =
var pt = skipTypes(s.typ, typedescInst)
assert skResult != s.kind

#note precedence: params override types
if optByRef in s.options: return true
elif sfByCopy in s.flags: return false
elif sfByCopy in s.flags: return false
elif tfByRef in pt.flags: return true
elif tfByCopy in pt.flags: return false
case pt.kind
Expand All @@ -153,3 +153,62 @@ proc ccgIntroducedPtr*(conf: ConfigRef; s: PSym, retType: PType): bool =
result = not (pt.kind in {tyVar, tyArray, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} or
pt.kind == tySet and mapSetType(conf, pt) == ctArray)

proc encodeName*(name: string): string =
result = mangle(name)
result = $result.len & result

proc makeUnique(m: BModule; s: PSym, name: string = ""): string =
result = if name == "": s.name.s else: name
result.add "__"
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
result.add "_u"
result.add $s.itemId.item

proc encodeSym*(m: BModule; s: PSym; makeUnique: bool = false): string =
#Module::Type
var name = s.name.s
if makeUnique:
name = makeUnique(m, s, name)
"N" & encodeName(s.owner.name.s) & encodeName(name) & "E"

proc encodeType*(m: BModule; t: PType): string =
result = ""
var kindName = ($t.kind)[2..^1]
kindName[0] = toLower($kindName[0])[0]
case t.kind
of tyObject, tyEnum, tyDistinct, tyUserTypeClass, tyGenericParam:
result = encodeSym(m, t.sym)
of tyGenericInst, tyUserTypeClassInst, tyGenericBody:
result = encodeName(t[0].sym.name.s)
result.add "I"
for i in 1..<t.len - 1:
result.add encodeType(m, t[i])
result.add "E"
of tySequence, tyOpenArray, tyArray, tyVarargs, tyTuple, tyProc, tySet, tyTypeDesc,
tyPtr, tyRef, tyVar, tyLent, tySink, tyStatic, tyUncheckedArray, tyOr, tyAnd, tyBuiltInTypeClass:
result =
case t.kind:
of tySequence: encodeName("seq")
else: encodeName(kindName)
result.add "I"
for i in 0..<t.len:
let s = t[i]
if s.isNil: continue
result.add encodeType(m, s)
result.add "E"
of tyRange:
var val = "range_"
if t.n[0].typ.kind in {tyFloat..tyFloat128}:
val.addFloat t.n[0].floatVal
val.add "_"
val.addFloat t.n[1].floatVal
else:
val.add $t.n[0].intVal & "_" & $t.n[1].intVal
result = encodeName(val)
of tyString..tyUInt64, tyPointer, tyBool, tyChar, tyVoid, tyAnything, tyNil, tyEmpty:
result = encodeName(kindName)
of tyAlias, tyInferred, tyOwned:
result = encodeType(m, t.elementType)
else:
assert false, "encodeType " & $t.kind

25 changes: 24 additions & 1 deletion compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ proc getTempCpp(p: BProc, t: PType, value: Rope): TLoc =
inc(p.labels)
result = TLoc(r: "T" & rope(p.labels) & "_", k: locTemp, lode: lodeTyp t,
storage: OnStack, flags: {})
linefmt(p, cpsStmts, "$1 $2 = $3;$n", [getTypeDesc(p.module, t, dkVar), result.r, value])
linefmt(p, cpsStmts, "auto $1 = $2;$n", [result.r, value])

proc getIntTemp(p: BProc): TLoc =
inc(p.labels)
Expand Down Expand Up @@ -2194,6 +2194,22 @@ proc updateCachedModule(m: BModule) =
cf.flags = {CfileFlag.Cached}
addFileToCompile(m.config, cf)

proc generateLibraryDestroyGlobals(graph: ModuleGraph; m: BModule; body: PNode; isDynlib: bool): PSym =
let procname = getIdent(graph.cache, "NimDestroyGlobals")
result = newSym(skProc, procname, m.idgen, m.module.owner, m.module.info)
result.typ = newProcType(m.module.info, m.idgen, m.module.owner)
result.typ.callConv = ccCDecl
incl result.flags, sfExportc
result.loc.r = "NimDestroyGlobals"
if isDynlib:
incl(result.loc.flags, lfExportLib)

let theProc = newNodeI(nkProcDef, m.module.info, bodyPos+1)
for i in 0..<theProc.len: theProc[i] = newNodeI(nkEmpty, m.module.info)
theProc[namePos] = newSymNode(result)
theProc[bodyPos] = body
result.ast = theProc

proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
## Also called from IC.
if sfMainModule in m.module.flags:
Expand All @@ -2205,6 +2221,13 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
if {optGenStaticLib, optGenDynLib, optNoMain} * m.config.globalOptions == {}:
for i in countdown(high(graph.globalDestructors), 0):
n.add graph.globalDestructors[i]
else:
var body = newNodeI(nkStmtList, m.module.info)
for i in countdown(high(graph.globalDestructors), 0):
body.add graph.globalDestructors[i]
body.flags.incl nfTransf # should not be further transformed
let dtor = generateLibraryDestroyGlobals(graph, m, body, optGenDynLib in m.config.globalOptions)
genProcAux(m, dtor)
if pipelineutils.skipCodegen(m.config, n): return
if moduleHasChanged(graph, m.module):
# if the module is cached, we don't regenerate the main proc
Expand Down
1 change: 1 addition & 0 deletions compiler/cgendata.nim
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ type
# unconditionally...
# nimtvDeps is VERY hard to cache because it's
# not a list of IDs nor can it be made to be one.
mangledPrcs*: HashSet[string]

TCGen = object of PPassContext # represents a C source file
s*: TCFileSections # sections of the C file
Expand Down
4 changes: 4 additions & 0 deletions compiler/cgmeth.nim
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym) =
g.config.isDefined("nimInternalNonVtablesTesting"):
localError(g.config, s.info, errGenerated, "method `" & s.name.s &
"` can be defined only in the same module with its type (" & s.typ.firstParamType.typeToString() & ")")
if sfImportc in s.flags:
localError(g.config, s.info, errGenerated, "method `" & s.name.s &
"` is not allowed to have 'importc' pragmas")

for i in 0..<g.methods.len:
let disp = g.methods[i].dispatcher
case sameMethodBucket(disp, s, multimethods = optMultiMethods in g.config.globalOptions)
Expand Down
10 changes: 9 additions & 1 deletion compiler/importer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,15 @@ proc myImportModule(c: PContext, n: var PNode, importStmtResult: PNode): PSym =
if belongsToStdlib(c.graph, result) and not startsWith(moduleName, stdPrefix) and
not startsWith(moduleName, "system/") and not startsWith(moduleName, "packages/"):
message(c.config, n.info, warnStdPrefix, realModule.name.s)
suggestSym(c.graph, n.info, result, c.graph.usageSym, false)

proc suggestMod(n: PNode; s: PSym) =
if n.kind == nkImportAs:
suggestMod(n[0], realModule)
elif n.kind == nkInfix:
suggestMod(n[2], s)
else:
suggestSym(c.graph, n.info, s, c.graph.usageSym, false)
suggestMod(n, result)
importStmtResult.add newSymNode(result, n.info)
#newStrNode(toFullPath(c.config, f), n.info)
else:
Expand Down
22 changes: 12 additions & 10 deletions compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ proc isLastReadImpl(n: PNode; c: var Con; scope: var Scope): bool =
result = false

proc isLastRead(n: PNode; c: var Con; s: var Scope): bool =
if not hasDestructor(c, n.typ): return true
# bug #23354; an object type could have a non-trival assignements when it is passed to a sink parameter
if not hasDestructor(c, n.typ) and (n.typ.kind != tyObject or isTrival(getAttachedOp(c.graph, n.typ, attachedAsgn))): return true

let m = skipConvDfa(n)
result = (m.kind == nkSym and sfSingleUsedTemp in m.sym.flags) or
Expand Down Expand Up @@ -318,7 +319,7 @@ proc isCriticalLink(dest: PNode): bool {.inline.} =

proc finishCopy(c: var Con; result, dest: PNode; isFromSink: bool) =
if c.graph.config.selectedGC == gcOrc:
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
let t = dest.typ.skipTypes(tyUserTypeClasses + {tyGenericInst, tyAlias, tySink, tyDistinct})
if cyclicType(c.graph, t):
result.add boolLit(c.graph, result.info, isFromSink or isCriticalLink(dest))

Expand Down Expand Up @@ -442,18 +443,19 @@ proc isCapturedVar(n: PNode): bool =

proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode =
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
let tmp = c.getTemp(s, n.typ, n.info)
if hasDestructor(c, n.typ):
let typ = n.typ.skipTypes({tyGenericInst, tyAlias, tySink})
let nTyp = n.typ.skipTypes(tyUserTypeClasses)
let tmp = c.getTemp(s, nTyp, n.info)
if hasDestructor(c, nTyp):
let typ = nTyp.skipTypes({tyGenericInst, tyAlias, tySink})
let op = getAttachedOp(c.graph, typ, attachedDup)
if op != nil and tfHasOwned notin typ.flags:
if sfError in op.flags:
c.checkForErrorPragma(n.typ, n, "=dup")
c.checkForErrorPragma(nTyp, n, "=dup")
else:
let copyOp = getAttachedOp(c.graph, typ, attachedAsgn)
if copyOp != nil and sfError in copyOp.flags and
sfOverridden notin op.flags:
c.checkForErrorPragma(n.typ, n, "=dup", inferredFromCopy = true)
c.checkForErrorPragma(nTyp, n, "=dup", inferredFromCopy = true)

let src = p(n, c, s, normal)
var newCall = newTreeIT(nkCall, src.info, src.typ,
Expand All @@ -470,7 +472,7 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode =
m.add p(n, c, s, normal)
c.finishCopy(m, n, isFromSink = true)
result.add m
if isLValue(n) and not isCapturedVar(n) and n.typ.skipTypes(abstractInst).kind != tyRef and c.inSpawn == 0:
if isLValue(n) and not isCapturedVar(n) and nTyp.skipTypes(abstractInst).kind != tyRef and c.inSpawn == 0:
message(c.graph.config, n.info, hintPerformance,
("passing '$1' to a sink parameter introduces an implicit copy; " &
"if possible, rearrange your program's control flow to prevent it") % $n)
Expand All @@ -479,8 +481,8 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode =
("cannot move '$1', passing '$1' to a sink parameter introduces an implicit copy") % $n)
else:
if c.graph.config.selectedGC in {gcArc, gcOrc, gcAtomicArc}:
assert(not containsManagedMemory(n.typ))
if n.typ.skipTypes(abstractInst).kind in {tyOpenArray, tyVarargs}:
assert(not containsManagedMemory(nTyp))
if nTyp.skipTypes(abstractInst).kind in {tyOpenArray, tyVarargs}:
localError(c.graph.config, n.info, "cannot create an implicit openArray copy to be passed to a sink parameter")
result.add newTree(nkAsgn, tmp, p(n, c, s, normal))
# Since we know somebody will take over the produced copy, there is
Expand Down
2 changes: 1 addition & 1 deletion compiler/liftdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1252,7 +1252,7 @@ proc inst(g: ModuleGraph; c: PContext; t: PType; kind: TTypeAttachedOp; idgen: I
else:
localError(g.config, info, "unresolved generic parameter")

proc isTrival(s: PSym): bool {.inline.} =
proc isTrival*(s: PSym): bool {.inline.} =
s == nil or (s.ast != nil and s.ast[bodyPos].len == 0)

proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo;
Expand Down
9 changes: 7 additions & 2 deletions compiler/msgs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -429,15 +429,20 @@ To create a stacktrace, rerun compilation with './koch temp $1 <file>', see $2 f
proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string, ignoreMsg: bool) =
if msg in fatalMsgs:
if conf.cmd == cmdIdeTools: log(s)
quit(conf, msg)
if conf.cmd != cmdIdeTools or msg != errFatal:
quit(conf, msg)
if msg >= errMin and msg <= errMax or
(msg in warnMin..hintMax and msg in conf.warningAsErrors and not ignoreMsg):
inc(conf.errorCounter)
conf.exitcode = 1'i8
if conf.errorCounter >= conf.errorMax:
# only really quit when we're not in the new 'nim check --def' mode:
if conf.ideCmd == ideNone:
quit(conf, msg)
when defined(nimsuggest):
#we need to inform the user that something went wrong when initializing NimSuggest
raiseRecoverableError(s)
else:
quit(conf, msg)
elif eh == doAbort and conf.cmd != cmdIdeTools:
quit(conf, msg)
elif eh == doRaise:
Expand Down
2 changes: 1 addition & 1 deletion compiler/parser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1427,7 +1427,7 @@ proc parseTypeDesc(p: var Parser, fullExpr = false): PNode =
result = newNodeP(nkObjectTy, p)
getTok(p)
of tkConcept:
result = nil
result = p.emptyNode
parMessage(p, "the 'concept' keyword is only valid in 'type' sections")
of tkVar: result = parseTypeDescKAux(p, nkVarTy, pmTypeDesc)
of tkOut: result = parseTypeDescKAux(p, nkOutTy, pmTypeDesc)
Expand Down
9 changes: 8 additions & 1 deletion compiler/pragmas.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1129,13 +1129,20 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wFatal: fatal(c.config, it.info, expectStrLit(c, it))
of wDefine: processDefine(c, it, sym)
of wUndef: processUndef(c, it)
of wCompile: processCompile(c, it)
of wCompile:
let m = sym.getModule()
incl(m.flags, sfUsed)
processCompile(c, it)
of wLink: processLink(c, it)
of wPassl:
let m = sym.getModule()
incl(m.flags, sfUsed)
let s = expectStrLit(c, it)
extccomp.addLinkOption(c.config, s)
recordPragma(c, it, "passl", s)
of wPassc:
let m = sym.getModule()
incl(m.flags, sfUsed)
let s = expectStrLit(c, it)
extccomp.addCompileOption(c.config, s)
recordPragma(c, it, "passc", s)
Expand Down
Loading

0 comments on commit 07dfc63

Please sign in to comment.