DIP62: Volatile type qualifier for unoptimizable variables in embedded programming
Johannes Pfau via Digitalmars-d
digitalmars-d at puremagic.com
Wed Jul 16 13:09:20 PDT 2014
Am Wed, 16 Jul 2014 21:59:57 +0200
schrieb Artur Skawina via Digitalmars-d <digitalmars-d at puremagic.com>:
> On 07/16/14 15:02, Johannes Pfau via Digitalmars-d wrote:
> > Am Tue, 15 Jul 2014 19:44:51 +0200
> > schrieb Artur Skawina via Digitalmars-d
> > <digitalmars-d at puremagic.com>:
> >
> >> Could you show one (concrete) example where using 'volatile' is
> >> better than my approach?
> >
> > I experimented a little more with Volatile!T and I don't think you
> > can make this example work:
> >
> > struct Timer
> > {
> > uint control;
> > uint data;
> > }
> >
> > enum timerA = (Volatile!Timer)* = cast()0xDEADBEAF;
> >
> > timerA.control |= 0b1;
>
> Thank you very much for showing actual code. There are many (wrong)
> assumptions being made in this thread (and the one on the gdc list).
> Claims like "A is required" or "B is impossible", where A and B are
> not actually defined and only vaguely described, do not usually lead
> to a productive dialogue. Concrete examples and code make it possible
> for the discussion to be about facts and not perceptions.
>
> struct Timer
> {
> uint control;
> uint data;
> }
>
> enum timerA = cast(Volatile!(Timer)*)0xDEADBEAF;
> //enum timerA = volatile_(cast(Timer*)0xDEADBEAF); // works too.
>
> void main() {
> timerA.control |= 0b1;
> }
>
> struct Volatile(PT) {
> PT raw;
>
> auto opDispatch(string M)() @property { return
> volatile_(mixin(q{&raw.}~M)); }
>
> auto opOpAssign(string OP, B)(B b) {
> auto a = load(*raw);
> auto r = mixin("a "~OP~" b");
> store(*raw, r);
> return this;
> }
>
> static:
> T load(T)(ref T v) {
> asm { "" : "+m" v; }
> T res = v;
> asm { "" : "+g" res; }
> return res;
> }
>
> T store(T)(ref T v, const T a) {
> asm { "" : : "m" v; }
> v = a;
> asm { "" : "+m" v; }
> return a;
> }
> }
> auto volatile_(A)(A a) { return Volatile!A(a); } // Just for IFTI.
>
>
> when compiled w/ "gdc -O1" results in
>
> 0000000000402949 <_Dmain>:
> 402949: b8 af be ad de mov $0xdeadbeaf,%eax
> 40294e: 8b 10 mov (%rax),%edx
> 402950: 83 ca 01 or $0x1,%edx
> 402953: 89 10 mov %edx,(%rax)
> 402955: b8 00 00 00 00 mov $0x0,%eax
> 40295a: c3 retq
>
> which is the exact op sequence you'd expect. Doing it as just one
> R-M-W op would be possible too, but that might not be supported by
> all HW/platforms.
> And, yes, gdc inlines it even at -O0, if @inline is used. But at -O0
> the generated code is /already/ huge and inefficient, hence not really
> usable in constrained mem environments.
>
> Obviously, this is just a proof of concept and the minimal
> implementation that can only handle your example. But it's enough to
> disprove the it-cannot-be-made-to-work-without-c-volatile claim. Are
> there any other examples of things that cannot be efficiently handled
> w/o a built-in volatile type qualifier?
>
> artur
Well I guess this is already decided anyway.
I think it's kinda ridiculous that D embedded code will only be usable
with strong optimization flags, but whatever. Maybe it works better
if the usage is restricted to basic types only.
More information about the Digitalmars-d
mailing list