Comment #0 by default_357-line — 2009-01-13T05:28:11Z
In GDC on ARM, the following code
struct Test {
uint* ptr;
uint write(uint i) { volatile (*ptr) = i; return i; }
}
void main() {
Test test; test.ptr = cast(uint*) 0xDEAD_BEEF;
test.write(0); test.write(0); test.write(0);
return;
}
generates this assembly: http://paste.dprogramming.com/dpep5uc3 .
Note how the 0 is only stored once, not thrice, in blatant violation of the volatile.
Comment #1 by default_357-line — 2009-01-13T05:31:36Z
Sorry. Please disregard for now. I'm seeing conflicting results.
Comment #2 by default_357-line — 2009-01-13T05:44:39Z
Right. Here we go. I had testcased it incorrectly.
The code to reproduce the error is
struct Test {
uint* ptr;
uint write(uint i) { volatile (*ptr) = i; return i; }
static Test opCall() { // it has to be returned by a function call, otherwise the error doesn't happen
Test res;
res.ptr = cast(uint*) 0xDEAF_D00D;
return res;
}
}
void main() {
auto mat = Test();
asm { "@baz"; }; // added to make sure it's the correct assembly this time
mat.write(0); mat.write(0); mat.write(0);
return;
}
And the assembly is here http://paste.dprogramming.com/dpag1p5d
Comment #3 by alex — 2012-10-09T17:00:38Z
Closing this since volatile is deprecated.
Comment #4 by turkeyman — 2012-10-10T01:25:21Z
(In reply to comment #3)
> Closing this since volatile is deprecated.
Really? It's still important... What's the work-around?
Comment #5 by ibuclaw — 2012-10-10T02:27:48Z
(In reply to comment #4)
> (In reply to comment #3)
> > Closing this since volatile is deprecated.
>
> Really? It's still important... What's the work-around?
It is indeed important. It's also now unreplicable. http://paste.dprogramming.com/dpsuffnm
Gonna put this down to a bug in gcc-4.1 that has since been fixed.
Comment #6 by ibuclaw — 2012-10-10T02:37:40Z
Note:
The D2-way of doing this is by using shared.
struct Test {
shared uint* ptr;
uint write(uint i) { (*ptr) = i; return i; }
}
void main() {
Test test; test.ptr = cast(uint*) 0xDEAD_BEEF;
test.write(0); test.write(0); test.write(0);
return;
}
Also guarantees that (*ptr) is stored thrice also.
----
_Dmain:
.fnstart
ldr r3, .L6
@baz
mov r0, #0
str r0, [r3]
str r0, [r3]
str r0, [r3]
bx lr
.fnend
Regards,
Iain
Comment #7 by turkeyman — 2012-10-10T02:57:56Z
(In reply to comment #6)
> Note:
>
> The D2-way of doing this is by using shared.
Really? I thought it was nothing more than a type-safety marker. So shared actually makes a variable volatile?
Comment #8 by ibuclaw — 2012-10-10T03:32:04Z
(In reply to comment #7)
> (In reply to comment #6)
> > Note:
> >
> > The D2-way of doing this is by using shared.
>
> Really? I thought it was nothing more than a type-safety marker. So shared
> actually makes a variable volatile?
Not the variable, but it's type is qualified as volatile, this produces subtly different codegen (IIRC volatile on the var would mean it is loaded thrice also). Given it's use in atomics, and that data-depending ordering is essential. I felt this to be important. Similarly for immutable, which sets the type as being const qualified.