Object file questions

Timo Sintonen via D.gnu d.gnu at puremagic.com
Sun Aug 17 00:57:15 PDT 2014


On Saturday, 16 August 2014 at 20:01:06 UTC, Artur Skawina via
D.gnu wrote:
> On 08/16/14 20:40, Artur Skawina wrote:
>>> How can I use this with struct members ?
>> 
>> One possibility would be to declare all members as 
>> `Volatile!...`, or
>
> I did not like that required dereference in the previous 
> version,
> and tried a different approach:
>
>    struct Timer
>    {
>        Volatile!uint control;
>        Volatile!uint data;
>    }
>
>    enum timerA = cast(Timer*)0xDEADBEAF;
>
>    int main() {
>       timerA.control |= 0b1;
>       timerA.control += 1;
>       timerA.control = 42;
>       int a = timerA.data - timerA.data;
>       int b = timerA.control;
>       return timerA.control;
>    }
>
>    version (GNU) {
>    static import gcc.attribute;
>    enum inline = gcc.attribute.attribute("forceinline");
>    }
> 
>    extern int volatile_dummy;
> 
>    @inline T volatile_load(T)(ref T v) nothrow {
>       asm { "" : "+m" v, "+m" volatile_dummy; }
>       T res = v;
>       asm { "" : "+g" res, "+m" v, "+m" volatile_dummy; }
>       return res;
>    }
>
>    @inline void volatile_store(T, A)(ref T v, A a) nothrow {
>       asm { "" : "+m" volatile_dummy : "m" v; }
>       v = a;
>       asm { "" : "+m" v, "+m" volatile_dummy; }
>    }
> 
>    struct Volatile(T) {
>       T raw;
>       nothrow: @inline:
>       @disable this(this);
>       void opAssign(A)(A a) { volatile_store(raw, a); }
>       T load() @property { return volatile_load(raw); }
>       alias load this;
>       void opOpAssign(string OP)(const T rhs) {
>            auto v = volatile_load(raw);
>            mixin("v " ~ OP ~ "= rhs;");
>            volatile_store(raw, v);
>       }
>    }
>
>
> artur

This seems to work. With inlining the code is quite compact.

Not tested yet but the code for these constructs looks correct:
for (f=0;f<50;f++) { regs.txreg = śomebuf[f] }
while (regs.status == 0) {}

What is the purpose of volatile_dummy? Even if it is not used,
the address for it is calculated in several places.

The struct members are defined saparately. This means the address
of every member is stored and fetched separately. The compiler
seems to remove some of these and use the pointer, but I am not
sure what happens when the structs are bigger.

It seems all loads and stores access the real memory, like
volatile should do. It is hard to follow the optimized code so I
am not yet sure that they have not been reordered in any way.

Anyway, this seems acceptable solution to me.

Johannes, is this good starting point to you or is your work with
compiler builtins giving us some more?


More information about the D.gnu mailing list