November 14, 2013
Am 14.11.2013 11:28, schrieb Walter Bright:
>
> This of course means that functions may wind up going through the
> dllimport indirection even for calling functions in the same dll, but it
> should work.

Also our suggested approach would not have this downside.

Think about phobos. All of phobos and druntime will be littered with export attributes. Do you really want all phobos and druntime from within the same dll to go through dll indirections? And what would happen when building phobos as static library? With your suggested behavior (export=dllimport if not specified otherwise) this would mean that even the phobos static library would have those indirections.

-- 
Kind Regards
Benjamin Thaut
November 14, 2013
Am 14.11.2013 08:36, schrieb Rainer Schuetze:
>
>
>
> As far as I understand, the optimization avoids generating code for
> template instances only _created_ (not defined) by imported modules,
> e.g. when needed for semantic analysis inside the imported module, but
> never actually referenced by generated code by the root modules.
>
> [OT: The problem of the current implementation is the detection of
> "only" in that definition, it fails too often leading to linker errors
> and the addition of that terrible -allinst switch. I had to disable the
> optimization for me before addition of that switch.]
>
> With respect to export I guess the optimization doesn't change much as
> multiple instances of the same template instance still can be found in
> different object files (maybe even less predictable).
>
> To avoid the trouble with templates, here is an idea for discussion:
>
> - templates definitions by themselves are never dllexport/dllimport
>
> - template instances are dllexport/dllimport with the proposed semantics
> of normal functions/variables if they are explicitely declared as
> "export" by an alias statement, e.g.
>
>    export alias templ!int exported_tmpl_int;
>
> - implicitely created template instances don't create dllexport
> versions, and use dllimport semantics if the declaration above is found
> in an import.

I actually like this idea. Everytime I actually had to dllexport / dllimport templates in C++ I knew beforehand which types I need the template exported for.

But what would should in a case like this:

class WeakReferenced(T)
{
  export __gshared WeakReferenced!T[] m_weakTable;
}

Note that the export is not applied to the template directly but instead to a specific member inside the template.

Should this be an error?

>
> - It's worse for the dllimport case, as data accesses to template
> variables will sometimes use the additional indirection, sometimes not.

Why exactly is that? Would that also be the case with the system proposed by the DIP? The dip never actually uses dllimport, so shouldn't it just work (tm)?

Kind Regards
Benjamin Thaut

November 14, 2013
On Thursday, 14 November 2013 at 13:31:30 UTC, Benjamin Thaut wrote:
> Am 14.11.2013 11:28, schrieb Walter Bright:
>>
>> This of course means that functions may wind up going through the
>> dllimport indirection even for calling functions in the same dll, but it
>> should work.
>
> Also our suggested approach would not have this downside.
>
> Think about phobos. All of phobos and druntime will be littered with export attributes. Do you really want all phobos and druntime from within the same dll to go through dll indirections? And what would happen when building phobos as static library? With your suggested behavior (export=dllimport if not specified otherwise) this would mean that even the phobos static library would have those indirections.

This thread have reached some end.

It has been shown in the beginning that linkers know how to get rid of the indirection here. If we are going to discuss the same thing again and again without even doing some experiment for the reality check, then we can stop right here.
November 14, 2013
Am 14.11.2013 20:54, schrieb deadalnix:
> On Thursday, 14 November 2013 at 13:31:30 UTC, Benjamin Thaut wrote:
>> Am 14.11.2013 11:28, schrieb Walter Bright:
>>>
>>> This of course means that functions may wind up going through the
>>> dllimport indirection even for calling functions in the same dll, but it
>>> should work.
>>
>> Also our suggested approach would not have this downside.
>>
>> Think about phobos. All of phobos and druntime will be littered with
>> export attributes. Do you really want all phobos and druntime from
>> within the same dll to go through dll indirections? And what would
>> happen when building phobos as static library? With your suggested
>> behavior (export=dllimport if not specified otherwise) this would mean
>> that even the phobos static library would have those indirections.
>
> This thread have reached some end.
>
> It has been shown in the beginning that linkers know how to get rid of
> the indirection here. If we are going to discuss the same thing again
> and again without even doing some experiment for the reality check, then
> we can stop right here.

No, linkers can not get of this indirection. Only whole program optimization can, and that won't happen in D (at least dmd) for quite some time. We had exactly that discussion in the old thread about the export attribute. See here: http://forum.dlang.org/thread/kvhu2c$2ikq$1@digitalmars.com#post-kvhu2c:242ikq:241:40digitalmars.com

But because Walter does not agree with the way we solved the problem in DIP 45 we have to go through everything again from the beginning.
And I'm certenly not going to accept a solution where we rely on some non implemented feature to remove indirections which will most likely not happen in the near future. The same already happend for virtual functions. The documentation states that the compiler might optimize them away, but in pratice this still does not happen, and most likely never will.

With DIP 45 we setteled for additional indirections to achive better usability and I'm ok with that. But what Walter suggests esentially means even more indirections and worse usability. And I'm not ok with that.

I also don't like that we have to go through everything again we already discussed in the old thread, but if Walter doesn't agree it has to be that way. So please try to contribute in a constructive manner, or leave out comments entierly.

Kind Regards
Benjamin Thaut
November 14, 2013
OK, I missed the point where everything started back again. This is being ridiculous.
November 14, 2013

On 14.11.2013 18:25, Benjamin Thaut wrote:
> Am 14.11.2013 08:36, schrieb Rainer Schuetze:
>>
>>
>>
>> As far as I understand, the optimization avoids generating code for
>> template instances only _created_ (not defined) by imported modules,
>> e.g. when needed for semantic analysis inside the imported module, but
>> never actually referenced by generated code by the root modules.
>>
>> [OT: The problem of the current implementation is the detection of
>> "only" in that definition, it fails too often leading to linker errors
>> and the addition of that terrible -allinst switch. I had to disable the
>> optimization for me before addition of that switch.]
>>
>> With respect to export I guess the optimization doesn't change much as
>> multiple instances of the same template instance still can be found in
>> different object files (maybe even less predictable).
>>
>> To avoid the trouble with templates, here is an idea for discussion:
>>
>> - templates definitions by themselves are never dllexport/dllimport
>>
>> - template instances are dllexport/dllimport with the proposed semantics
>> of normal functions/variables if they are explicitely declared as
>> "export" by an alias statement, e.g.
>>
>>    export alias templ!int exported_tmpl_int;
>>
>> - implicitely created template instances don't create dllexport
>> versions, and use dllimport semantics if the declaration above is found
>> in an import.
>
> I actually like this idea. Everytime I actually had to dllexport /
> dllimport templates in C++ I knew beforehand which types I need the
> template exported for.
>
> But what would should in a case like this:
>
> class WeakReferenced(T)
> {
>    export __gshared WeakReferenced!T[] m_weakTable;
> }

According to the rule above "export" on the template definition has no effect, only when it is instantiated with

export alias WeakReferenced!int WeakRefIntArray;

>
> Note that the export is not applied to the template directly but instead
> to a specific member inside the template.
>
> Should this be an error?

Maybe. Another rule might be that only the declarations actually annotated with "export" gets exported with the instantiation, so you could add "export" to the whole class or only some declaraations.

>
>>
>> - It's worse for the dllimport case, as data accesses to template
>> variables will sometimes use the additional indirection, sometimes not.
>
> Why exactly is that? Would that also be the case with the system
> proposed by the DIP? The dip never actually uses dllimport, so shouldn't
> it just work (tm)?
>

The problem is that the template instantiation can exist without the compiler seeing the alias:

-----------
module a;
class tmpl(T) { static shared int var; }

-----------
module b;
import a;
export alias tmpl!int tmpl_int;

-----------
module c;
import b;
int func() { return tmpl!int.var; } // uses dllimport access with indirection

-----------
module d;
import a;
int fund() { return tmpl!int.var; } // uses standard access without indirection

compiling c and d as single files will silently generate different code, because when compiling d, the export alias is never seen.

(this cannot happen with standard variables, only when declared multiple times, but differently, with extern(C/C++/System)).
November 15, 2013
Am 15.11.2013 00:38, schrieb Rainer Schuetze:
>
> Maybe. Another rule might be that only the declarations actually
> annotated with "export" gets exported with the instantiation, so you
> could add "export" to the whole class or only some declaraations.
>

I don't think this is a good idea. It should be possible to put "export:" on top of a file and just export everything. If you limit it to decelerations the following would work:

export __gshared int g_var;

but the following wouldn't:

export __gshared int g_var = 0;

Although it would really produce equivalent code.

>
> compiling c and d as single files will silently generate different code,
> because when compiling d, the export alias is never seen.
>
> (this cannot happen with standard variables, only when declared multiple
> times, but differently, with extern(C/C++/System)).

And do you already have a idea how we could work around this problem?

Kind Regards
Benjamin Thaut
November 15, 2013
On 11/14/2013 3:37 AM, Benjamin Thaut wrote:
> Am 14.11.2013 11:28, schrieb Walter Bright:
>> On 11/12/2013 2:23 PM, Martin Nowak wrote:
>>
>> One possibility is modules listed on the command line are regarded as
>> export==dllexport, and other modules as export==dllimport.
>>
>> This of course means that functions may wind up going through the
>> dllimport indirection even for calling functions in the same dll, but it
>> should work.
>
> That doesns't work for the case where a dll "A" uses a dll "B".
> In that case export has to mean "dllexport" for all modules of A but "dllimport"
> for all modules of B.

I don't follow. If you're compiling A, you're specifying A modules on the command line, and those will regard the B modules as dllimport.

November 15, 2013
On 11/14/2013 5:31 AM, Benjamin Thaut wrote:
> Am 14.11.2013 11:28, schrieb Walter Bright:
>>
>> This of course means that functions may wind up going through the
>> dllimport indirection even for calling functions in the same dll, but it
>> should work.
>
> Also our suggested approach would not have this downside.
>
> Think about phobos. All of phobos and druntime will be littered with export
> attributes. Do you really want all phobos and druntime from within the same dll
> to go through dll indirections? And what would happen when building phobos as
> static library? With your suggested behavior (export=dllimport if not specified
> otherwise) this would mean that even the phobos static library would have those
> indirections.
>

It's not that bad. Phobos can be built by specifying all the files on the command line.

Also, at least on Windows, you can call functions in a DLL without saying dllimport on them and suffering a layer of indirection. The magic happens in the import library, which provides the relevant thunk. It's about 15 years since I worked on this stuff, so I might be a bit fuzzy on the details.
November 15, 2013
"Walter Bright" <newshound2@digitalmars.com> wrote in message news:l64imh$27na$1@digitalmars.com...
>
> Also, at least on Windows, you can call functions in a DLL without saying dllimport on them and suffering a layer of indirection. The magic happens in the import library, which provides the relevant thunk. It's about 15 years since I worked on this stuff, so I might be a bit fuzzy on the details.

The symbol in the import library just translates to an import table indirection.

The trick you may have been thinking of is system dlls (kernel32.dll, user32.dll etc) are always loaded at the same address, so a little hackery will let you bypass the import table.