wrong result/codegen for atomicOp!"-="(ulong, uint) using DMD -m64. tested on win64 only, using DMD-2.071.2. problem does not occur with DMD -m32 or ldc2-1.1.0-b3 -m64.
-----
version(DigitalMars)version(D_LP64){
import std.stdio : writeln;
import core.atomic : atomicOp;
shared ulong foo = 2;
uint bar = 1;
atomicOp!"-="( foo, bar );
writeln( "foo = ", foo ); // foo = 4294967297
}
Comment #1 by ag0aep6g — 2016-11-01T13:24:22Z
Same happens with -m32 and smaller types:
----
void main()
{
import std.stdio : writeln;
import core.atomic : atomicOp;
shared uint foo = 2;
ubyte bar = 1;
atomicOp!"-="( foo, bar );
writeln( "foo = ", foo ); // foo = 257
}
----
Also happens on Linux.
Looks like a bug in druntime code (core.atomic) rather than dmd. I think it works with LDC because they've added a path of their own to druntime [1].
[1] https://github.com/ldc-developers/druntime/blob/049b8efdf0daebcc1cfe690c5cf7585125c1ff72/src/core/atomic.d#L177
Comment #2 by safety0ff.bugz — 2016-11-01T21:05:37Z
(In reply to ag0aep6g from comment #1)
>
> Looks like a bug in druntime code (core.atomic) rather than dmd.
Yup, atomicFetchSub [1] doesn't widen the modifier before negating it.
This is necessary when the modifier is unsigned and narrower than the value's type.
[1] https://github.com/dlang/druntime/blob/master/src/core/atomic.d#L684