Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,11 @@ proc isLastReadImpl(n: PNode; c: var Con; scope: var Scope): bool =

template hasDestructorOrAsgn(c: var Con, typ: PType): bool =
# bug #23354; an object type could have a non-trivial assignements when it is passed to a sink parameter
hasDestructor(c, typ) or (c.graph.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and
hasDestructor(c, typ) or (c.graph.config.selectedGC == gcRefc and typ.kind == tyString) or (c.graph.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for seq?

typ.kind == tyObject and not isTrivial(getAttachedOp(c.graph, typ, attachedAsgn)))

proc isLastRead(n: PNode; c: var Con; s: var Scope): bool =
if not hasDestructorOrAsgn(c, n.typ): return true
if not hasDestructorOrAsgn(c, n.typ.skipTypes({tyGenericInst, tyAlias, tySink})): return true

let m = skipConvDfa(n)
result = isLastReadImpl(n, c, s)
Expand Down Expand Up @@ -286,7 +286,9 @@ proc deepAliases(dest, ri: PNode): bool =
return aliases(dest, ri) != no

proc genSink(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
if (c.inLoopCond == 0 and (isFullyUnpackedTuple(dest) or IsDecl in flags or
if c.graph.config.selectedGC == gcRefc and dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyString:
result = newFastAsgnStmt(dest, callCodegenProc(c.graph, "moveString", dest.info, ri))
elif (c.inLoopCond == 0 and (isFullyUnpackedTuple(dest) or IsDecl in flags or
(isAnalysableFieldAccess(dest, c.owner) and isFirstWrite(dest, c)))) or
isNoInit(dest) or IsReturn in flags:
# optimize sink call into a bitwise memcopy
Expand Down Expand Up @@ -352,6 +354,9 @@ proc genCopyNoCheck(c: var Con; dest, ri: PNode; a: TTypeAttachedOp): PNode =
assert ri.typ != nil

proc genCopy(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag]): PNode =
if c.graph.config.selectedGC == gcRefc and dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyString:
result = newAsgnStmt(dest, ri)
return
if c.inEnsureMove > 0:
localError(c.graph.config, ri.info, errFailedMove, "cannot move '" & $ri &
"', which introduces an implicit copy")
Expand Down
2 changes: 2 additions & 0 deletions compiler/liftdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,8 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of tyString:
if useNoGc(c, t):
useSeqOrStrOp(c, t, body, x, y)
elif c.g.config.selectedGC == gcRefc:
defaultOp(c, t, body, x, y)
elif tfHasAsgn in t.flags:
discard considerUserDefinedOp(c, t, body, x, y)
else:
Expand Down
2 changes: 1 addition & 1 deletion compiler/semtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2430,7 +2430,7 @@ proc processMagicType(c: PContext, m: PSym) =
of mString:
setMagicType(c.config, m, tyString, szUncomputedSize)
rawAddSon(m.typ, getSysType(c.graph, m.info, tyChar))
if optSeqDestructors in c.config.globalOptions:
if optSeqDestructors in c.config.globalOptions or c.config.selectedGC == gcRefc:
incl m.typ, tfHasAsgn
of mCstring:
setMagicIntegral(c.config, m, tyCstring, c.config.target.ptrSize)
Expand Down
9 changes: 9 additions & 0 deletions lib/system/sysstr.nim
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} =
if str == nil: NimString(nil)
else: toNimStr(str, str.len)

proc moveString(src: NimString): NimString {.compilerRtl.} =
if src == nil:
result = src
else:
if (src.reserved and strlitFlag) != 0:
result = toOwnedCopy(src)
else:
result = src

proc copyString(src: NimString): NimString {.compilerRtl.} =
## Expects `src` to be initialized (len and terminating zero set)
if src != nil:
Expand Down
Loading