Object file questions
Artur Skawina via D.gnu
d.gnu at puremagic.com
Sun Aug 17 06:15:12 PDT 2014
On 08/17/14 10:49, Johannes Pfau via D.gnu wrote:
> That's a good start. Can you also get unary operators working?
> e.g
> TimerB++;
Unary ops are easy. If you mean post-inc and post-dec -- that's a
language problem. At least for volatile, they will cause a compile
error; for atomic ops the naive `post-op->tmp-load+op+tmp` rewrite
can introduce bugs... D would need to make the post-ops overloadable
to get rid of these issues.
> Do you think it's possible to combine this with the other solution you
> posted for struct fields? Or do we need separate Volatile!T and
> VolatileField!T types?
Right now, I'd prefer this approach:
--------------------------------------------------------------
module volat;
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; }
}
@inline void volatile_barrier(T)(ref T v) nothrow {
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 b) {
volatile_barrier(raw);
mixin("raw " ~ OP ~ "= b;");
volatile_barrier(raw);
}
T opUnary(string OP)() {
volatile_barrier(raw);
auto result = mixin(OP ~ "raw");
volatile_barrier(raw);
return result;
}
}
--------------------------------------------------------------
import volat;
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;
--timerA.data;
timerA.control /= 2;
return b;
}
--------------------------------------------------------------
compiles to:
--------------------------------------------------------------
0000000000403620 <_Dmain>:
403620: ba af be ad de mov $0xdeadbeaf,%edx
403625: b9 b3 be ad de mov $0xdeadbeb3,%ecx
40362a: 83 0a 01 orl $0x1,(%rdx)
40362d: 83 02 01 addl $0x1,(%rdx)
403630: c7 02 2a 00 00 00 movl $0x2a,(%rdx)
403636: 8b 42 04 mov 0x4(%rdx),%eax
403639: 8b 72 04 mov 0x4(%rdx),%esi
40363c: 8b 02 mov (%rdx),%eax
40363e: 83 c0 01 add $0x1,%eax
403641: 89 02 mov %eax,(%rdx)
403643: 83 6a 04 01 subl $0x1,0x4(%rdx)
403647: d1 2a shrl (%rdx)
403649: c3 retq
--------------------------------------------------------------
Do you see any problems with it? (Other than gcc not removing
that dead constant load)
[The struct-with-volatile-fields can be built from a "normal"
struct at CT. But that's just syntax sugar.]
artur
More information about the D.gnu
mailing list