Skip to content

Commit

Permalink
Merge branch 'devel' into pr_sink_refc
Browse files Browse the repository at this point in the history
  • Loading branch information
ringabout authored Mar 13, 2024
2 parents 4644bb1 + 78c834d commit e8b83a1
Show file tree
Hide file tree
Showing 32 changed files with 385 additions and 125 deletions.
19 changes: 15 additions & 4 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2250,9 +2250,15 @@ proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =

proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
var a: TLoc = initLocExpr(p, n[0])
putIntoDest(p, d, n,
ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]),
a.storage)
if p.module.compileToCpp:
# fixes for const qualifier; bug #12703; bug #19588
putIntoDest(p, d, n,
ropecg(p.module, "#cstrToNimstr((NCSTRING) $1)", [rdLoc(a)]),
a.storage)
else:
putIntoDest(p, d, n,
ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]),
a.storage)
gcUsage(p.config, n)

proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
Expand Down Expand Up @@ -2470,7 +2476,12 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
genDollar(p, e, d, "#nimFloat32ToStr($1)")
else:
genDollar(p, e, d, "#nimFloatToStr($1)")
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
of mCStrToStr:
if p.module.compileToCpp:
# fixes for const qualifier; bug #12703; bug #19588
genDollar(p, e, d, "#cstrToNimstr((NCSTRING) $1)")
else:
genDollar(p, e, d, "#cstrToNimstr($1)")
of mStrToStr, mUnown: expr(p, e[1], d)
of generatedMagics: genCall(p, e, d)
of mEnumToStr:
Expand Down
26 changes: 17 additions & 9 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ proc mangleProc(m: BModule; s: PSym; makeUnique: bool): string =
proc fillBackendName(m: BModule; s: PSym) =
if s.loc.r == "":
var result: Rope
if s.kind in routineKinds and optCDebug in m.g.config.globalOptions and
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:
Expand Down Expand Up @@ -1193,12 +1193,15 @@ proc isReloadable(m: BModule; prc: PSym): bool =
proc isNonReloadable(m: BModule; prc: PSym): bool =
return m.hcrOn and sfNonReloadable in prc.flags

proc parseVFunctionDecl(val: string; name, params, retType, superCall: var string; isFnConst, isOverride, isMemberVirtual: var bool; isCtor: bool, isFunctor=false) =
proc parseVFunctionDecl(val: string; name, params, retType, superCall: var string; isFnConst, isOverride, isMemberVirtual, isStatic: var bool; isCtor: bool, isFunctor=false) =
var afterParams: string = ""
if scanf(val, "$*($*)$s$*", name, params, afterParams):
if name.strip() == "operator" and params == "": #isFunctor?
parseVFunctionDecl(afterParams, name, params, retType, superCall, isFnConst, isOverride, isMemberVirtual, isCtor, true)
parseVFunctionDecl(afterParams, name, params, retType, superCall, isFnConst, isOverride, isMemberVirtual, isStatic, isCtor, true)
return
if name.find("static ") > -1:
isStatic = true
name = name.replace("static ", "")
isFnConst = afterParams.find("const") > -1
isOverride = afterParams.find("override") > -1
isMemberVirtual = name.find("virtual ") > -1
Expand Down Expand Up @@ -1231,8 +1234,8 @@ proc genMemberProcHeader(m: BModule; prc: PSym; result: var Rope; asPtr: bool =
var typDesc = getTypeDescWeak(m, typ, check, dkParam)
let asPtrStr = rope(if asPtr: "_PTR" else: "")
var name, params, rettype, superCall: string = ""
var isFnConst, isOverride, isMemberVirtual: bool = false
parseVFunctionDecl(prc.constraint.strVal, name, params, rettype, superCall, isFnConst, isOverride, isMemberVirtual, isCtor)
var isFnConst, isOverride, isMemberVirtual, isStatic: bool = false
parseVFunctionDecl(prc.constraint.strVal, name, params, rettype, superCall, isFnConst, isOverride, isMemberVirtual, isStatic, isCtor)
genMemberProcParams(m, prc, superCall, rettype, name, params, check, true, false)
let isVirtual = sfVirtual in prc.flags or isMemberVirtual
var fnConst, override: string = ""
Expand All @@ -1241,6 +1244,8 @@ proc genMemberProcHeader(m: BModule; prc: PSym; result: var Rope; asPtr: bool =
if isFnConst:
fnConst = " const"
if isFwdDecl:
if isStatic:
result.add "static "
if isVirtual:
rettype = "virtual " & rettype
if isOverride:
Expand Down Expand Up @@ -1987,8 +1992,11 @@ proc genTypeSection(m: BModule, n: PNode) =
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 != nkSym): continue
if sfExportc in n[i][0][p].sym.flags:
discard getTypeDescAux(m, n[i][0][p].typ, intSet, descKindFromSymKind(n[i][0][p].sym.kind))
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, n[i][0][p].typ, intSet, descKindFromSymKind(n[i][0][p].sym.kind))
discard getTypeDescAux(m.g.generatedHeader, s.typ, intSet, descKindFromSymKind(s.sym.kind))
40 changes: 20 additions & 20 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, formatFloat]
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,62 +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 =
proc encodeName*(name: string): string =
result = mangle(name)
result = $result.len & result

proc makeUnique(m: BModule; s: PSym, name: string = ""): string =
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 =
proc encodeSym*(m: BModule; s: PSym; makeUnique: bool = false): string =
#Module::Type
var name = s.name.s
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 =
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:
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:
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 =
result =
case t.kind:
of tySequence: encodeName("seq")
of tySequence: encodeName("seq")
else: encodeName(kindName)
result.add "I"
for i in 0..<t.len:
let s = t[i]
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 "_"
if t.n[0].typ.kind in {tyFloat..tyFloat128}:
val.addFloat t.n[0].floatVal
val.add "_"
val.addFloat t.n[1].floatVal
else:
else:
val.add $t.n[0].intVal & "_" & $t.n[1].intVal
result = encodeName(val)
of tyString..tyUInt64, tyPointer, tyBool, tyChar, tyVoid, tyAnything, tyNil, tyEmpty:
of tyString..tyUInt64, tyPointer, tyBool, tyChar, tyVoid, tyAnything, tyNil, tyEmpty:
result = encodeName(kindName)
of tyAlias, tyInferred, tyOwned:
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
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
3 changes: 2 additions & 1 deletion 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
8 changes: 7 additions & 1 deletion compiler/jsgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,13 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mEqProc: applyFormat("($1 == $2)", "($1 == $2)")
of mUnaryMinusI: applyFormat("negInt($1)", "-($1)")
of mUnaryMinusI64: applyFormat("negInt64($1)", "-($1)")
of mAbsI: applyFormat("absInt($1)", "Math.abs($1)")
of mAbsI:
let typ = n[1].typ.skipTypes(abstractVarRange)
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "absInt64")
applyFormat("absInt64($1)", "absInt64($1)")
else:
applyFormat("absInt($1)", "Math.abs($1)")
of mNot: applyFormat("!($1)", "!($1)")
of mUnaryPlusI: applyFormat("+($1)", "+($1)")
of mBitnotI:
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
1 change: 0 additions & 1 deletion compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1849,7 +1849,6 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
n[genericParamsPos] = c.graph.emptyNode
# for LL we need to avoid wrong aliasing
let params = copyTree n.typ.n
n[paramsPos] = params
s.typ = n.typ
for i in 1..<params.len:
if params[i].typ.kind in {tyTypeDesc, tyGenericParam,
Expand Down
7 changes: 6 additions & 1 deletion compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
# a[b] = c
decodeBC(rkNode)
let idx = regs[rb].intVal.int
assert regs[ra].kind == rkNode
let arr = regs[ra].node
case arr.kind
of nkTupleConstr: # refer to `opcSlice`
Expand All @@ -826,7 +827,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of nkStrKinds:
src.strVal[int(realIndex)] = char(regs[rc].intVal)
of nkBracket:
src[int(realIndex)] = regs[rc].node
if regs[rc].kind == rkInt:
src[int(realIndex)] = newIntNode(nkIntLit, regs[rc].intVal)
else:
assert regs[rc].kind == rkNode
src[int(realIndex)] = regs[rc].node
else:
stackTrace(c, tos, pc, "opcWrArr internal error")
else:
Expand Down
2 changes: 2 additions & 0 deletions compiler/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2050,6 +2050,8 @@ proc genSetConstr(c: PCtx, n: PNode, dest: var TDest) =
c.freeTemp(a)

proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
if tfUnion in n.typ.flags: # bug #22708 # bug #13481
globalError(c.config, n.info, "object with '{.union.}' pragmas is not supported by VM")
if dest < 0: dest = c.getTemp(n.typ)
let t = n.typ.skipTypes(abstractRange+{tyOwned}-{tyTypeDesc})
if t.kind == tyRef:
Expand Down
8 changes: 3 additions & 5 deletions doc/backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ which will likely make your program crash at runtime.
The name `NimMain` can be influenced via the `--nimMainPrefix:prefix` switch.
Use `--nimMainPrefix:MyLib` and the function to call is named `MyLibNimMain`.

When compiling to static or dynamic libraries, they don't call destructors of global variables as normal Nim programs would do. A C API `NimDestroyGlobals` is provided to call these global destructors.


### Nim invocation example from C

Expand Down Expand Up @@ -371,11 +373,7 @@ The manual mentions that [Nim strings are implicitly convertible to
cstrings](manual.html#types-cstring-type) which makes interaction usually
painless. Most C functions accepting a Nim string converted to a
`cstring` will likely not need to keep this string around and by the time
they return the string won't be needed anymore. However, for the rare cases
where a Nim string has to be preserved and made available to the C backend
as a `cstring`, you will need to manually prevent the string data
from being freed with [GC_ref](system.html#GC_ref,string) and [GC_unref](
system.html#GC_unref,string).
they return the string won't be needed anymore.

A similar thing happens with C code invoking Nim code which returns a
`cstring`. Consider the following proc:
Expand Down
3 changes: 0 additions & 3 deletions doc/nimc.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,9 +503,6 @@ To link against ``nimrtl.dll`` use the command:
nim c -d:useNimRtl myprog.nim
```

**Note**: Currently the creation of ``nimrtl.dll`` with thread support has
never been tested and is unlikely to work!


Additional compilation switches
===============================
Expand Down
Loading

0 comments on commit e8b83a1

Please sign in to comment.