fixes #25208; generates a copy for opcLdConst in the assignments (#25211)

fixes #25208


```nim
type Conf = object
  val: int

const defaultConf = Conf(val: 123)
static:
  var conf: Conf
  conf = defaultConf
```

```nim
# opcLdConst is now always valid. We produce the necessary copy in the
# assignments now:
```

A `opcLdConst` is generated for `defaultConf` in `conf = defaultConf`.
According to the comment above, we need to handle the copy for
assignments of `opcLdConst`
This commit is contained in:
ringabout
2025-10-17 00:22:06 +08:00
committed by GitHub
parent 8f3bdb6951
commit f009ea6c3e
2 changed files with 25 additions and 3 deletions

View File

@@ -1609,12 +1609,12 @@ proc genAdditionalCopy(c: PCtx; n: PNode; opc: TOpcode;
c.freeTemp(cc)
proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
dest, idx, value: TRegister) =
dest, idx, value: TRegister; enforceCopy = false) =
# opcLdObj et al really means "load address". We sometimes have to create a
# copy in order to not introduce false aliasing:
# mylocal = a.b # needs a copy of the data!
assert n.typ != nil
if needsAdditionalCopy(n):
if needsAdditionalCopy(n) or enforceCopy:
genAdditionalCopy(c, n, opc, dest, idx, value)
else:
c.gABC(n, opc, dest, idx, value)
@@ -1663,11 +1663,14 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
of nkSym:
let s = le.sym
checkCanEval(c, le)
let isLdConst = ri.kind == nkSym and ri.sym.kind == skConst and
dontInlineConstant(ri, if ri.sym.astdef != nil: ri.sym.astdef else: ri.sym.typ.n)
# assigning a constant (opcLdConst) to something; need to copy its value
if s.isGlobal:
withTemp(tmp, le.typ):
c.gen(le, tmp, {gfNodeAddr})
let val = c.genx(ri)
c.preventFalseAlias(le, opcWrDeref, tmp, 0, val)
c.preventFalseAlias(le, opcWrDeref, tmp, 0, val, isLdConst)
c.freeTemp(val)
else:
if s.kind == skForVar: c.setSlot s

View File

@@ -794,3 +794,22 @@ block: # bug #23925
static: # bug #21353
var s: proc () = default(proc ())
doAssert s == nil
# bug #25208
type Conf = object
val: int
const defaultConf = Conf(val: 123)
template foo2323(conf) =
assert conf.val == 123
var conf2 = conf
assert conf2.val == 123
static:
var conf: Conf = defaultConf
conf = defaultConf # removing this results in the expected output
conf.val = 2
foo2323(defaultConf)