Object file questions

Johannes Pfau via D.gnu d.gnu at puremagic.com
Sun Aug 17 01:51:10 PDT 2014


Am Sun, 17 Aug 2014 07:57:15 +0000
schrieb "Timo Sintonen" <t.sintonen at luukku.com>:

> 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?

You mean __builtin_volatile_load/store? I'm not sure if compiler
barriers and these builtins are 100% equal, I think I managed to
produce example code where the barriers didn't work 100% as expected.
But these builtins will need to be introduced anyway as
core.bitop.volatileLoad or whatever final name the DMD devs decide on.

Regarding nocode/typeinfo/noinit/GNU_nomoduleinfo: I think these are
useful anyway. The linker can strip these out, but I don't want to rely
on the linker and on the user to know all special linker flags only to
avoid some binary bloat which can be avoided in the compiler.

But overall this approach looks fine.



More information about the D.gnu mailing list