September 24, 2016
Am Wed, 31 Aug 2016 12:28:58 +0000
schrieb Timo Sintonen <t.sintonen@luukku.com>:

> On Wednesday, 31 August 2016 at 10:12:21 UTC, Johannes Pfau wrote:
> > Am Wed, 31 Aug 2016 09:07:49 +0000
> > schrieb Timo Sintonen <t.sintonen@luukku.com>:
> >
> > 
> >> 
> >> The original functions had force_inline attribute. The
> >> compiler said it can not inline because the body is not
> >> available. Is this because they are templates or is this
> >> because of the intrinsic call? These calls are often in time
> >> critical places and inlining them is very important.
> >> 
> >
> > This is probably a old GDC/DMDFE bug. Cross-module inlining
> > (i.e. function with force-inline in one module, caller in
> > another module) wasn't possible with older frontend versions.
> > It should be possible now, but it is not implemented in GDC.
> > Can you post a simple test case? Usually templated methods are
> > the only methods which should work with cross module inlining.
> > 
> Anything that access the Volatile members:
> 
> int test()
> { return uart3.sr; }
> 
> error: inlining failed in call to always_inline 'load': function
> body not available
> T load @property { return volatileLoad(&raw); }
> 
> 

Sorry, it took me some time to get back to this. Anyway, forceinline works for me if I use it in the same module: https://paste.gnome.org/p1nlnvagl

If I instead move the main function to a different file, I can reproduce the error. This is the known cross-module inlining problem. I'll probably have a look at this soon. https://forum.dlang.org/post/mzevpbxsyvdrcyjuwhuu@forum.dlang.org
September 24, 2016
Am Wed, 31 Aug 2016 19:06:37 +0000
schrieb Timo Sintonen <t.sintonen@luukku.com>:

> On Wednesday, 31 August 2016 at 10:12:21 UTC, Johannes Pfau wrote:
> 
> >> There was @disable this(this)
> >> This prevents to use a location as argument to a function,
> >> like:
> >> print(timer.count). Is there any reason to have this line or
> >> not?
> >
> > I guess timer is a (enum) pointer to a struct and count is a
> > Volatile!T
> > field in that struct?
> Yes
> 
> > But then timer.count does not return a address, it returns the
> > value of
> > count? Unless of course print(X) takes its argument by ref or
> > alias.
> I want to use them just by value.
> 
> >
> > The reason for @disable this(this) is to disable copying of the
> > struct.
> > The compiler otherwise accesses T raw in a 'non-volatile' way
> > when
> > copying the value. In D we can only have a postblit function,
> > but we
> > cannot reimplement the copying. opAssign can only be used in
> > some cases:
> >     Foo f;
> >     auto f2 = Foo();
> >     auto f3 = f2;
> >     f = Foo();
> >     f = f2;
> >
> > Only the last two lines call opAssign. So "auto f3 = f2" could
> > copy a Volatile!T in a non-volatile way. This is the reason for
> > @disable this(this), AFAIK.
> > 
> I think I somehow get the point even if I do not fully understand the explanation.

See https://dlang.org/spec/struct.html#struct-postblit :
"1. blitting the fields, i.e. copying the bits [...] The first part is
done automatically by the language,"

So assume we have a (Volatile!uint)* called 'value' pointing to 0x4. Volatile!uint is a struct with a uint raw member. Now if we do something like this:

Volatile!uint copy = *value;

This tells DMD that copy is a struct with one uint field on the stack. Now to create this stack variable the compiler will copy the 4 bytes from 0x4 for the field to the stack (The rule #1 quoted above). But the compiler does not know that the data at 0x4 is 'volatile'. So it would insert a normal / 'non-volatile' load. And this load is then subject to the optimizations we want to avoid with Volatile!T.

So we somehow have to prevent the compiler from making such copies. The only way to do this is @disable this(this).

> But it is too restrictive if I always need to have a getter function or assign the value first to a temporary variable to use the value in a function call.

I think there's a misunderstanding here:
The problem only occurs if you pass a _Volatile!T_ by value:

void foo(Volatile!uint value) {}
foo(timer.count);

But if you only need the payload data you can pass the _T_ type instead and everything works fine, even with @disable this(this): The alias this implements this implicit convertion. This means the compiler will call load for you when preparing the function arguments (with the standard D side effect rules, i.e. LTR evaluation)

void foo(uint value) {}
foo(timer.count); // <-- load is called here

If you really want to pass a Volatile!T type (or a struct containing Volatile!T fields) the only safe way is pass by reference / pointer. You have ta avoid copying / reading the data, but you can of course refer to it's memory location / address:

void foo(ref Volatile!uint value) {}
foo(timer.count);

> 
> Anyway, I think it is a gdc bug that the error message comes from the called function that has nothing to do with this. The error should show the function call where the disabled copy operation is.
> 

That's a valid point, but handling this is a DMD task. Please report this at issues.dlang.org.
1 2
Next ›   Last »