You're running into a C code generator double-evaluation bug recently 
introduced for projects using `--gc:arc|orc|atomicArc`.

I haven't inspected all callsites of the `pop` template, but assuming that the 
popped stack-entries always become re-usable, you can move the `move` call into 
the template, like so:
    
    
    template pop*(): Value =
      ...
      move Stack[SP]
    
    
    Run

Apart from working around the compiler bug, this also removes the need to use 
`move` at `pop` callsites.

* * *

For anyone interested in fixing the bug, the problematic part are the following 
[lines](https://github.com/nim-lang/Nim/blob/7d9fe106ecd70bf99b9f3224430debfe10060ce1/compiler/ccgexprs.nim#L2366-L2368)
 in `ccgexprs.nim`, introduced by 
[this](https://github.com/nim-lang/Nim/pull/22288) PR.

The AST for a new `=wasMoved` call statement is constructed, using the `move` 
call's operand as the argument. Generating the code for said call statement 
then results in the `move` call's operand being code-gen and emitted twice.

A quick-fix (which might not work with the C++ backend, I haven't tested it) 
could be replacing the aforementioned lines with:
    
    
    var b = default(TLoc)
    initLocExpr(p, b, newSymNode(op))
    linefmt(p, "$1($2);$n", [rdLoc(b), byRefLoc(a)]
    
    
    Run

However, this doesn't fix the related issue of `move` behaving differently with 
the JavaScript and VM backends (no `=wasMoved` call is inserted there) than 
compared to with the C backend.

Ultimately, lowering the `mMove` magic during the `injectdestructors` pass 
would be the more robust fix.

Reply via email to