https://wiki.dlang.org/api.php?action=feedcontributions&user=Ingrater&feedformat=atomD Wiki - User contributions [en]2024-03-28T08:42:33ZUser contributionsMediaWiki 1.31.2https://wiki.dlang.org/?title=DIP45&diff=8188DIP452017-01-31T12:39:13Z<p>Ingrater: </p>
<hr />
<div>{| class="wikitable" <br />
!Title: <br />
!'''making export an attribute''' <br />
|-<br />
|DIP: <br />
|45 <br />
|- <br />
|Version: <br />
|3 <br />
|- <br />
|Status: <br />
|Draft <br />
|- <br />
|Created: <br />
|2013-08-27<br />
|- <br />
|Last Modified: <br />
|2017-01-30<br />
|- <br />
|Author: <br />
|Benjamin Thaut, Martin Nowak, David Nadlinger<br />
|- <br />
|Links: <br />
|<br />
<br />
DConf 2016 Talk: https://www.youtube.com/watch?v=MQRHxI2SrYM<br />
<br />
*http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
*http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
*http://d.puremagic.com/issues/show_bug.cgi?id=9816 <br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior need to be changed in serveral ways to make it<br />
work on Windows and allow better code generation for other<br />
plattforms. The Rationale section explains the problems and shows how<br />
this DIP solves them.<br />
<br />
==Description==<br />
<br />
* The '''export''' protection level should be turned into a '''export''' attribute.<br />
* '''export''' might appear in front of '''module''' to indicate that the implementation specific module symbols should be exported.<br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute.<br />
* There should be only one meaning of 'export'.<br />
* On *nix systems default symbol visibility is changed to hidden, and only symbols marked with export become visible.<br />
<br />
==Rationale==<br />
<br />
===Turning export into an attribute===<br />
<br />
Currently '''export''' is a protection level, the highest level of<br />
visibility actually. This however conflicts with the need to export<br />
'protected' and 'private' symbols. Consider a Base class in a shared library.<br />
<br />
<syntaxhighlight lang=D><br />
module sharedLib;<br />
<br />
class Base { <br />
protected final void doSomething() { ... } <br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module executable;<br />
import sharedLib;<br />
<br />
class Derived : Base { <br />
public void func() <br />
{ <br />
doSomething(); <br />
} <br />
}<br />
</syntaxhighlight><br />
<br />
In the above example 'doSomething' should only be visible to derived<br />
classes but it still needs to be exportable from a shared library.<br />
Therefor '''export''' should become a normal attribute which behaves<br />
orthogonal to protection.<br />
<br />
Also consider the following example in which the template will access a private function. Because the template is instanced on the user side and not within the shared library it is required to export the private function so that the template can access it from outside the shared library.<br />
<br />
<syntaxhighlight lang=D><br />
module dll;<br />
<br />
void copy(T)(T val)<br />
{<br />
copyImpl(&val, T.sizeof);<br />
}<br />
<br />
export private copyImpl(void* mem, size_t size)<br />
{<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=D><br />
module exe;<br />
import dll;<br />
<br />
void main(string[] args)<br />
{<br />
int bar = 0;<br />
copy(bar); // template will be instanciated in the exe but needs access to the copyImpl function.<br />
}<br />
</syntaxhighlight><br />
<br />
Another special case are voldemord types. If a voldemord type is used it needs to be exported explictily.<br />
<syntaxhighlight lang=D><br />
module lib;<br />
<br />
export auto makeSomething(int v)<br />
{<br />
export struct Something<br />
{<br />
int i;<br />
}<br />
<br />
return Something(v);<br />
}<br />
</syntaxhighlight><br />
<br />
At first glance exporting a template doesn't make much sense. But consider the following example:<br />
<br />
<syntaxhighlight lang=D><br />
module lib;<br />
import std.stdio;<br />
<br />
export struct Foo(T)<br />
{<br />
T value;<br />
void print() { writefln("%s", value); }<br />
}<br />
<br />
__gshared Foo!int g_inst = Foo!int(5);<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=D><br />
module exe;<br />
import lib;<br />
<br />
void main(string[] args)<br />
{<br />
auto f = Foo!int(5);<br />
f.print();<br />
}<br />
</syntaxhighlight><br />
<br />
When compiling the executable module exe which uses the module lib compiled into a dll the compiler will attempt to reuse the instance of Foo!int from the lib module. This however only works if the instance has been exported from the dll. As a result exporting a tempalte should be equivalent to exporting any instance created from this template. In code:<br />
<br />
<syntaxhighlight lang=D><br />
export struct(T) { ... }<br />
<br />
// is equivalent to<br />
template (T)<br />
{<br />
export struct { ... }<br />
}<br />
</syntaxhighlight><br />
<br />
===Exporting module compiler internal symbols===<br />
<br />
Each D module has a set of compiler internal symbols which may be referenced. To allow for exporting these symbols '''export''' is allowed in front of '''module''' to indicate that the compiler internal symbols should be exported. Example:<br />
<br />
<syntaxhighlight lang=D> export module sharedLib;<br />
<br />
void testSomething(T)(T val)<br />
{<br />
assert(T.sizeof > 8);<br />
}<br />
</syntaxhighlight><br />
<br />
Please note that in the above example there is not a single member of the module marked with '''export'''. But still it is required to export the compiler internal module symbols as the template will be instanciated on the user side of the shared library and thus will access the 'assert' module symbol. If the 'assert' module symbol is not exported this would lead to a linker error.<br />
The compiler internal module symbols should not be exported by default. Consider building a D-Dll with a pure C interface. In this case you don't want to export any compiler internal symbols as you want to have a very well defined C interface of your dll.<br />
<br />
===export attribute inference===<br />
<br />
Currently export has to be specified in a lot of places to export all<br />
neccessary functions and data symbols. Export should be transitive for aggregate types (structs/classes) so that when exporting a aggregate type export is applied to all public & protected members without the need to add export to every single public and protected member.<br />
<br />
<syntaxhighlight lang="D"><br />
module sharedLib;<br />
<br />
export class A // compiler internal members should be exported (e.g. vtable, type info)<br />
{ <br />
private: <br />
int m_a;<br />
<br />
static int s_b; // should not be exported<br />
<br />
void internalFunc() { ... } // should not be exported<br />
<br />
protected: <br />
void interalFunc2() { ... } // should be exported<br />
<br />
public: <br />
class Inner // compiler internal members should be exported<br />
{ <br />
__gshared int s_inner; // should be exported<br />
<br />
void innerMethod() { ... } // should be exported <br />
}<br />
<br />
void method() { ... } // should be exported <br />
}<br />
</syntaxhighlight><br />
<br />
===A single meaning of '''export'''===<br />
<br />
The classical solution to handle dllexport/dllimport attributes on<br />
Windows is to define a macro that depending on the current build<br />
setting expands to __declspec(dllexport) or to __declspec(dllimport).<br />
This complicates the build setup and means that object files for a<br />
static library can't be mixed well with object files for a DLL.<br />
Instead we propose that exported data definitions are accompanied with<br />
an _imp_ pointer and always accessed through them. See the<br />
implementation detail section for how this will work for<br />
[[#Data_Symbols|data symbols]] and [[#Function_Symbols|function<br />
symbols]]. That way a compiled object file can be used for a DLL or a<br />
static library. And vice versa an object file can be linked against an<br />
import library or a static library.<br />
<br />
===Access TLS variables===<br />
<br />
Currently it is not possible to access TLS variables across shared<br />
library boundaries on Windows. This might be implemented in the future. (see<br />
[[#TLS_variables|implementation details]] for a proposal).<br />
<br />
===Change symbol visibility on *nix systems===<br />
<br />
When building shared libraries on *nix systems all symbols are visible<br />
by default. This is a main reason for the performance impact of PIC<br />
because every data access and every function call go through the GOT<br />
or PLT indirection. It also leads to long loading time because an<br />
excessive number of relocations have to be processed. <br />
Making all symbols hidden by default significantly reduces the size of the dynamic symbol table (faster<br />
lookup and smaller libraries). See http://gcc.gnu.org/wiki/Visibility<br />
and http://people.redhat.com/drepper/dsohowto.pdf for more details.<br />
<br />
Also making every symbol accessible can inadvertently cause ABI<br />
dependencies making it harder to maintain libraries.<br />
<br />
Furthermore, hiding functions by default enables much more aggressive compiler optimizations, to the benefit of both executable performance and code size. Some examples for this are elision of completely inlined functions, optimization of function signatures/calling conventions, partial inlining/constant propagation, … Some of these optimization opportunities also positively affect compile times, as evidenced by an experimental LDC patch (see [https://github.com/ldc-developers/ldc/pull/483 LDC #483], although LTO is required to fully exploit this).<br />
<br />
==Implementation Details==<br />
<br />
=== Windows ===<br />
<br />
==== Data Symbols ====<br />
<br />
===== Accessing through code =====<br />
<br />
For data symbols the 'export' attribute always means 'dllexport' when<br />
defining a symbol and 'dllimport' when accessing a symbol. That is<br />
accessing an exported variable is done through dereferencing it's<br />
corresponding import symbols. When defining an exported variable the<br />
compiler will emit a corresponding import symbol that is initialized<br />
with address of the variable. The import symbol can be located in the<br />
read only data segment. The mangling of the import symbol consists of<br />
the '_imp_'/'__imp_' (Win32/Win64) prefix followed by the mangled name<br />
of the variable. Import symbols itself are not exported. When an<br />
exported variable of the same module is accessed the compiler might<br />
avoid the indirection and perform a direct access.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export __gshared int var = 5;<br />
__gshared int* _imp__D1a3vari = &var; // import symbol generated by the compiler<br />
<br />
void func()<br />
{<br />
var = 3; // accesses var directly, because in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
var = 5; // accesses through indirection because var is marked as export and in a different module<br />
// *_imp__D1a3vari = 5; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
===== Referencing in constant data ======<br />
<br />
When referencing data symbols in the contents of some other data symbol there will be a additional level of indirection which needs to be removed during program startup.<br />
<br />
<syntaxhighlight lang=D><br />
module dll;<br />
<br />
__gshared int var = 5;<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=D><br />
module exe;<br />
import dll;<br />
<br />
__gshared int* pvar = &var; // address not known at compile time<br />
</syntaxhighlight><br />
<br />
As the address of var is not known at compile time so pvar will point to the entry in the import table for 'var'. At program startup, before any other D code runs, pvar will be dereferenced once. E.g. the following operation will be executed on pvar.<br />
<br />
<syntaxhighlight lang=D><br />
pvar = *cast(int**)pvar;<br />
</syntaxhighlight><br />
<br />
This removes the additional indirection added by the import table and correctly initializes the static memory for pvar. This might happen in various other cases, mostly when generating initializers, type infos, vtables, module infos and other static data the compiler produces.<br />
<br />
==== Function Symbols ====<br />
<br />
For function symbols the 'export' attribute always means 'dllexport'<br />
when defining a function and will be ignored when calling it.<br />
Calling an exported function is always done through the original symbol.<br />
In an import library the original symbol is defined as trampoline that simply calls the<br />
dereferenced _imp_ pointer.<br />
Thus calling an exported function will be compatible with both import<br />
libraries and static libraries, in the later case without indirection.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export void func()<br />
{<br />
}<br />
<br />
void bar()<br />
{<br />
func(); // call func; // directly<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
func(); // call func; // through trampoline<br />
}<br />
<br />
// definitions in the import library generated by implib<br />
void func()<br />
{<br />
asm<br />
{<br />
naked;<br />
jmp [_imp_func];<br />
}<br />
}<br />
void function() _imp_func = &func; // filled at runtime with the DLL address of func<br />
</syntaxhighlight><br />
<br />
==== TLS variables ====<br />
<br />
Note: This is not implemented at the moment.<br />
<br />
For each exported TLS variable the compiler should generate a function<br />
that returns the address of the TLS variable in the current<br />
thread. These internal methods should have some kind of unified prefix<br />
to mark them as TLS import helpers. I propose "__tlsstub_". These<br />
internal methods are also exported. So when accessing an exported TLS<br />
variable the compiler will insert a call to<br />
'_imp__D1a15__tlsstub_g_tlsFZPi' instead. As an optimization accesses<br />
to exported TLS variables within the same module can be performed<br />
directly.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export int g_tls = 5; // thread local storage<br />
<br />
export int* __tlsstub__g_tls() // generated by the compiler<br />
{<br />
return &g_tls;<br />
}<br />
alias _imp___tlsstub__g_tls = __tlsstub__g_tls; // also generated by the compiler<br />
<br />
void func()<br />
{<br />
g_tls = 3; // direct access because marked as export and in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
g_tls = 10; // access through _imp___tlsstub__g_tls function because marked as export and in a different module<br />
// *_imp___tlsstub__g_tls() = 10; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
=== *nix ===<br />
<br />
Note: This is not yet implemented.<br />
<br />
On *nix systems the default symbols visibility should be changed to<br />
hidden, i.e. -fvisibility=hidden argument of gcc. Only symbols marked<br />
with '''export''' should get the attribute visible.<br />
<br />
This is trivial to implement on GDC and LDC.<br />
<br />
=== Linking archives into shared libraries ===<br />
<br />
When linking archives into shared libraries the exported symbols from the archive will also be exported from the resulting shared library. Most often this is unwanted and may lead to inadvertent ABI dependencies.<br />
To accomplish this we'll provide a tool that strips export attributes from archives.<br />
<br />
== Copyright ==<br />
<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=8187DIP452017-01-31T12:38:03Z<p>Ingrater: </p>
<hr />
<div>{| class="wikitable" <br />
!Title: <br />
!'''making export an attribute''' <br />
|-<br />
|DIP: <br />
|45 <br />
|- <br />
|Version: <br />
|3 <br />
|- <br />
|Status: <br />
|Draft <br />
|- <br />
|Created: <br />
|2013-08-27<br />
|- <br />
|Last Modified: <br />
|2017-01-30<br />
|- <br />
|Author: <br />
|Benjamin Thaut, Martin Nowak, David Nadlinger<br />
|- <br />
|Links: <br />
|<br />
<br />
DConf 2016 Talk: https://www.youtube.com/watch?v=MQRHxI2SrYM<br />
<br />
*http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
*http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
*http://d.puremagic.com/issues/show_bug.cgi?id=9816 <br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior need to be changed in serveral ways to make it<br />
work on Windows and allow better code generation for other<br />
plattforms. The Rationale section explains the problems and shows how<br />
this DIP solves them.<br />
<br />
==Description==<br />
<br />
* The '''export''' protection level should be turned into a '''export''' attribute.<br />
* '''export''' might appear in front of '''module''' to indicate that the implementation specific module symbols should be exported.<br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute.<br />
* There should be only one meaning of 'export'.<br />
* On *nix systems default symbol visibility is changed to hidden, and only symbols marked with export become visible.<br />
<br />
==Rationale==<br />
<br />
===Turning export into an attribute===<br />
<br />
Currently '''export''' is a protection level, the highest level of<br />
visibility actually. This however conflicts with the need to export<br />
'protected' and 'private' symbols. Consider a Base class in a shared library.<br />
<br />
<syntaxhighlight lang=D><br />
module sharedLib;<br />
<br />
class Base { <br />
protected final void doSomething() { ... } <br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module executable;<br />
import sharedLib;<br />
<br />
class Derived : Base { <br />
public void func() <br />
{ <br />
doSomething(); <br />
} <br />
}<br />
</syntaxhighlight><br />
<br />
In the above example 'doSomething' should only be visible to derived<br />
classes but it still needs to be exportable from a shared library.<br />
Therefor '''export''' should become a normal attribute which behaves<br />
orthogonal to protection.<br />
<br />
Also consider the following example in which the template will access a private function. Because the template is instanced on the user side and not within the shared library it is required to export the private function so that the template can access it from outside the shared library.<br />
<br />
<syntaxhighlight lang=D><br />
module dll;<br />
<br />
void copy(T)(T val)<br />
{<br />
copyImpl(&val, T.sizeof);<br />
}<br />
<br />
export private copyImpl(void* mem, size_t size)<br />
{<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=D><br />
module exe;<br />
import dll;<br />
<br />
void main(string[] args)<br />
{<br />
int bar = 0;<br />
copy(bar); // template will be instanciated in the exe but needs access to the copyImpl function.<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
TODO: Voldemord types<br />
<br />
Another special case are voldemord types. If a voldemord type is used it needs to be exported explictily.<br />
<syntaxhighlight lang=D><br />
module lib;<br />
<br />
export auto makeSomething(int v)<br />
{<br />
export struct Something<br />
{<br />
int i;<br />
}<br />
<br />
return Something(v);<br />
}<br />
</syntaxhighlight><br />
<br />
At first glance exporting a template doesn't make much sense. But consider the following example:<br />
<br />
<syntaxhighlight lang=D><br />
module lib;<br />
import std.stdio;<br />
<br />
export struct Foo(T)<br />
{<br />
T value;<br />
void print() { writefln("%s", value); }<br />
}<br />
<br />
__gshared Foo!int g_inst = Foo!int(5);<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=D><br />
module exe;<br />
import lib;<br />
<br />
void main(string[] args)<br />
{<br />
auto f = Foo!int(5);<br />
f.print();<br />
}<br />
</syntaxhighlight><br />
<br />
When compiling the executable module exe which uses the module lib compiled into a dll the compiler will attempt to reuse the instance of Foo!int from the lib module. This however only works if the instance has been exported from the dll. As a result exporting a tempalte should be equivalent to exporting any instance created from this template. In code:<br />
<br />
<syntaxhighlight lang=D><br />
export struct(T) { ... }<br />
<br />
// is equivalent to<br />
template (T)<br />
{<br />
export struct { ... }<br />
}<br />
</syntaxhighlight><br />
<br />
===Exporting module compiler internal symbols===<br />
<br />
Each D module has a set of compiler internal symbols which may be referenced. To allow for exporting these symbols '''export''' is allowed in front of '''module''' to indicate that the compiler internal symbols should be exported. Example:<br />
<br />
<syntaxhighlight lang=D> export module sharedLib;<br />
<br />
void testSomething(T)(T val)<br />
{<br />
assert(T.sizeof > 8);<br />
}<br />
</syntaxhighlight><br />
<br />
Please note that in the above example there is not a single member of the module marked with '''export'''. But still it is required to export the compiler internal module symbols as the template will be instanciated on the user side of the shared library and thus will access the 'assert' module symbol. If the 'assert' module symbol is not exported this would lead to a linker error.<br />
The compiler internal module symbols should not be exported by default. Consider building a D-Dll with a pure C interface. In this case you don't want to export any compiler internal symbols as you want to have a very well defined C interface of your dll.<br />
<br />
===export attribute inference===<br />
<br />
Currently export has to be specified in a lot of places to export all<br />
neccessary functions and data symbols. Export should be transitive for aggregate types (structs/classes) so that when exporting a aggregate type export is applied to all public & protected members without the need to add export to every single public and protected member.<br />
<br />
<syntaxhighlight lang="D"><br />
module sharedLib;<br />
<br />
export class A // compiler internal members should be exported (e.g. vtable, type info)<br />
{ <br />
private: <br />
int m_a;<br />
<br />
static int s_b; // should not be exported<br />
<br />
void internalFunc() { ... } // should not be exported<br />
<br />
protected: <br />
void interalFunc2() { ... } // should be exported<br />
<br />
public: <br />
class Inner // compiler internal members should be exported<br />
{ <br />
__gshared int s_inner; // should be exported<br />
<br />
void innerMethod() { ... } // should be exported <br />
}<br />
<br />
void method() { ... } // should be exported <br />
}<br />
</syntaxhighlight><br />
<br />
===A single meaning of '''export'''===<br />
<br />
The classical solution to handle dllexport/dllimport attributes on<br />
Windows is to define a macro that depending on the current build<br />
setting expands to __declspec(dllexport) or to __declspec(dllimport).<br />
This complicates the build setup and means that object files for a<br />
static library can't be mixed well with object files for a DLL.<br />
Instead we propose that exported data definitions are accompanied with<br />
an _imp_ pointer and always accessed through them. See the<br />
implementation detail section for how this will work for<br />
[[#Data_Symbols|data symbols]] and [[#Function_Symbols|function<br />
symbols]]. That way a compiled object file can be used for a DLL or a<br />
static library. And vice versa an object file can be linked against an<br />
import library or a static library.<br />
<br />
===Access TLS variables===<br />
<br />
Currently it is not possible to access TLS variables across shared<br />
library boundaries on Windows. This might be implemented in the future. (see<br />
[[#TLS_variables|implementation details]] for a proposal).<br />
<br />
===Change symbol visibility on *nix systems===<br />
<br />
When building shared libraries on *nix systems all symbols are visible<br />
by default. This is a main reason for the performance impact of PIC<br />
because every data access and every function call go through the GOT<br />
or PLT indirection. It also leads to long loading time because an<br />
excessive number of relocations have to be processed. <br />
Making all symbols hidden by default significantly reduces the size of the dynamic symbol table (faster<br />
lookup and smaller libraries). See http://gcc.gnu.org/wiki/Visibility<br />
and http://people.redhat.com/drepper/dsohowto.pdf for more details.<br />
<br />
Also making every symbol accessible can inadvertently cause ABI<br />
dependencies making it harder to maintain libraries.<br />
<br />
Furthermore, hiding functions by default enables much more aggressive compiler optimizations, to the benefit of both executable performance and code size. Some examples for this are elision of completely inlined functions, optimization of function signatures/calling conventions, partial inlining/constant propagation, … Some of these optimization opportunities also positively affect compile times, as evidenced by an experimental LDC patch (see [https://github.com/ldc-developers/ldc/pull/483 LDC #483], although LTO is required to fully exploit this).<br />
<br />
==Implementation Details==<br />
<br />
=== Windows ===<br />
<br />
==== Data Symbols ====<br />
<br />
===== Accessing through code =====<br />
<br />
For data symbols the 'export' attribute always means 'dllexport' when<br />
defining a symbol and 'dllimport' when accessing a symbol. That is<br />
accessing an exported variable is done through dereferencing it's<br />
corresponding import symbols. When defining an exported variable the<br />
compiler will emit a corresponding import symbol that is initialized<br />
with address of the variable. The import symbol can be located in the<br />
read only data segment. The mangling of the import symbol consists of<br />
the '_imp_'/'__imp_' (Win32/Win64) prefix followed by the mangled name<br />
of the variable. Import symbols itself are not exported. When an<br />
exported variable of the same module is accessed the compiler might<br />
avoid the indirection and perform a direct access.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export __gshared int var = 5;<br />
__gshared int* _imp__D1a3vari = &var; // import symbol generated by the compiler<br />
<br />
void func()<br />
{<br />
var = 3; // accesses var directly, because in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
var = 5; // accesses through indirection because var is marked as export and in a different module<br />
// *_imp__D1a3vari = 5; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
===== Referencing in constant data ======<br />
<br />
When referencing data symbols in the contents of some other data symbol there will be a additional level of indirection which needs to be removed during program startup.<br />
<br />
<syntaxhighlight lang=D><br />
module dll;<br />
<br />
__gshared int var = 5;<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=D><br />
module exe;<br />
import dll;<br />
<br />
__gshared int* pvar = &var; // address not known at compile time<br />
</syntaxhighlight><br />
<br />
As the address of var is not known at compile time so pvar will point to the entry in the import table for 'var'. At program startup, before any other D code runs, pvar will be dereferenced once. E.g. the following operation will be executed on pvar.<br />
<br />
<syntaxhighlight lang=D><br />
pvar = *cast(int**)pvar;<br />
</syntaxhighlight><br />
<br />
This removes the additional indirection added by the import table and correctly initializes the static memory for pvar. This might happen in various other cases, mostly when generating initializers, type infos, vtables, module infos and other static data the compiler produces.<br />
<br />
==== Function Symbols ====<br />
<br />
For function symbols the 'export' attribute always means 'dllexport'<br />
when defining a function and will be ignored when calling it.<br />
Calling an exported function is always done through the original symbol.<br />
In an import library the original symbol is defined as trampoline that simply calls the<br />
dereferenced _imp_ pointer.<br />
Thus calling an exported function will be compatible with both import<br />
libraries and static libraries, in the later case without indirection.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export void func()<br />
{<br />
}<br />
<br />
void bar()<br />
{<br />
func(); // call func; // directly<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
func(); // call func; // through trampoline<br />
}<br />
<br />
// definitions in the import library generated by implib<br />
void func()<br />
{<br />
asm<br />
{<br />
naked;<br />
jmp [_imp_func];<br />
}<br />
}<br />
void function() _imp_func = &func; // filled at runtime with the DLL address of func<br />
</syntaxhighlight><br />
<br />
==== TLS variables ====<br />
<br />
Note: This is not implemented at the moment.<br />
<br />
For each exported TLS variable the compiler should generate a function<br />
that returns the address of the TLS variable in the current<br />
thread. These internal methods should have some kind of unified prefix<br />
to mark them as TLS import helpers. I propose "__tlsstub_". These<br />
internal methods are also exported. So when accessing an exported TLS<br />
variable the compiler will insert a call to<br />
'_imp__D1a15__tlsstub_g_tlsFZPi' instead. As an optimization accesses<br />
to exported TLS variables within the same module can be performed<br />
directly.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export int g_tls = 5; // thread local storage<br />
<br />
export int* __tlsstub__g_tls() // generated by the compiler<br />
{<br />
return &g_tls;<br />
}<br />
alias _imp___tlsstub__g_tls = __tlsstub__g_tls; // also generated by the compiler<br />
<br />
void func()<br />
{<br />
g_tls = 3; // direct access because marked as export and in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
g_tls = 10; // access through _imp___tlsstub__g_tls function because marked as export and in a different module<br />
// *_imp___tlsstub__g_tls() = 10; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
=== *nix ===<br />
<br />
Note: This is not yet implemented.<br />
<br />
On *nix systems the default symbols visibility should be changed to<br />
hidden, i.e. -fvisibility=hidden argument of gcc. Only symbols marked<br />
with '''export''' should get the attribute visible.<br />
<br />
This is trivial to implement on GDC and LDC.<br />
<br />
=== Linking archives into shared libraries ===<br />
<br />
When linking archives into shared libraries the exported symbols from the archive will also be exported from the resulting shared library. Most often this is unwanted and may lead to inadvertent ABI dependencies.<br />
To accomplish this we'll provide a tool that strips export attributes from archives.<br />
<br />
== Copyright ==<br />
<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=8185DIP452017-01-30T12:19:18Z<p>Ingrater: </p>
<hr />
<div>{| class="wikitable" <br />
!Title: <br />
!'''making export an attribute''' <br />
|-<br />
|DIP: <br />
|45 <br />
|- <br />
|Version: <br />
|2 <br />
|- <br />
|Status: <br />
|Draft <br />
|- <br />
|Created: <br />
|2013-08-27<br />
|- <br />
|Last Modified: <br />
|2017-01-30<br />
|- <br />
|Author: <br />
|Benjamin Thaut, Martin Nowak, David Nadlinger<br />
|- <br />
|Links: <br />
|<br />
<br />
DConf 2016 Talk: https://www.youtube.com/watch?v=MQRHxI2SrYM<br />
<br />
*http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
*http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
*http://d.puremagic.com/issues/show_bug.cgi?id=9816 <br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior need to be changed in serveral ways to make it<br />
work on Windows and allow better code generation for other<br />
plattforms. The Rationale section explains the problems and shows how<br />
this DIP solves them.<br />
<br />
==Description==<br />
<br />
* The '''export''' protection level should be turned into a '''export''' attribute.<br />
* '''export''' might appear in front of '''module''' to indicate that the implementation specific module symbols should be exported.<br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute.<br />
* There should be only one meaning of 'export'.<br />
* On *nix systems default symbol visibility is changed to hidden, and only symbols marked with export become visible.<br />
<br />
==Rationale==<br />
<br />
===Turning export into an attribute===<br />
<br />
Currently '''export''' is a protection level, the highest level of<br />
visibility actually. This however conflicts with the need to export<br />
'protected' and 'private' symbols. Consider a Base class in a shared library.<br />
<br />
<syntaxhighlight lang=D><br />
module sharedLib;<br />
<br />
class Base { <br />
protected final void doSomething() { ... } <br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module executable;<br />
import sharedLib;<br />
<br />
class Derived : Base { <br />
public void func() <br />
{ <br />
doSomething(); <br />
} <br />
}<br />
</syntaxhighlight><br />
<br />
In the above example 'doSomething' should only be visible to derived<br />
classes but it still needs to be exportable from a shared library.<br />
Therefor '''export''' should become a normal attribute which behaves<br />
orthogonal to protection.<br />
<br />
Also consider the following example in which the template will access a private function. Because the template is instanced on the user side and not within the shared library it is required to export the private function so that the template can access it from outside the shared library.<br />
<br />
<syntaxhighlight lang=D><br />
module dll;<br />
<br />
void copy(T)(T val)<br />
{<br />
copyImpl(&val, T.sizeof);<br />
}<br />
<br />
export private copyImpl(void* mem, size_t size)<br />
{<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=D><br />
module exe;<br />
import dll;<br />
<br />
void main(string[] args)<br />
{<br />
int bar = 0;<br />
copy(bar); // template will be instanciated in the exe but needs access to the copyImpl function.<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
TODO: Voldemord types<br />
<br />
===Exporting module compiler internal symbols===<br />
<br />
Each D module has a set of compiler internal symbols which may be referenced. To allow for exporting these symbols '''export''' is allowed in front of '''module''' to indicate that the compiler internal symbols should be exported. Example:<br />
<br />
<syntaxhighlight lang=D> export module sharedLib;<br />
<br />
void testSomething(T)(T val)<br />
{<br />
assert(T.sizeof > 8);<br />
}<br />
</syntaxhighlight><br />
<br />
Please note that in the above example there is not a single member of the module marked with '''export'''. But still it is required to export the compiler internal module symbols as the template will be instanciated on the user side of the shared library and thus will access the 'assert' module symbol. If the 'assert' module symbol is not exported this would lead to a linker error.<br />
The compiler internal module symbols should not be exported by default. Consider building a D-Dll with a pure C interface. In this case you don't want to export any compiler internal symbols as you want to have a very well defined C interface of your dll.<br />
<br />
===export attribute inference===<br />
<br />
Currently export has to be specified in a lot of places to export all<br />
neccessary functions and data symbols. Export should be transitive for aggregate types (structs/classes) so that when exporting a aggregate type export is applied to all public & protected members without the need to add export to every single public and protected member.<br />
<br />
<syntaxhighlight lang="D"><br />
module sharedLib;<br />
<br />
export class A // compiler internal members should be exported (e.g. vtable, type info)<br />
{ <br />
private: <br />
int m_a;<br />
<br />
static int s_b; // should not be exported<br />
<br />
void internalFunc() { ... } // should not be exported<br />
<br />
protected: <br />
void interalFunc2() { ... } // should be exported<br />
<br />
public: <br />
class Inner // compiler internal members should be exported<br />
{ <br />
__gshared int s_inner; // should be exported<br />
<br />
void innerMethod() { ... } // should be exported <br />
}<br />
<br />
void method() { ... } // should be exported <br />
}<br />
</syntaxhighlight><br />
<br />
===A single meaning of '''export'''===<br />
<br />
The classical solution to handle dllexport/dllimport attributes on<br />
Windows is to define a macro that depending on the current build<br />
setting expands to __declspec(dllexport) or to __declspec(dllimport).<br />
This complicates the build setup and means that object files for a<br />
static library can't be mixed well with object files for a DLL.<br />
Instead we propose that exported data definitions are accompanied with<br />
an _imp_ pointer and always accessed through them. See the<br />
implementation detail section for how this will work for<br />
[[#Data_Symbols|data symbols]] and [[#Function_Symbols|function<br />
symbols]]. That way a compiled object file can be used for a DLL or a<br />
static library. And vice versa an object file can be linked against an<br />
import library or a static library.<br />
<br />
===Access TLS variables===<br />
<br />
Currently it is not possible to access TLS variables across shared<br />
library boundaries on Windows. This might be implemented in the future. (see<br />
[[#TLS_variables|implementation details]] for a proposal).<br />
<br />
===Change symbol visibility on *nix systems===<br />
<br />
When building shared libraries on *nix systems all symbols are visible<br />
by default. This is a main reason for the performance impact of PIC<br />
because every data access and every function call go through the GOT<br />
or PLT indirection. It also leads to long loading time because an<br />
excessive number of relocations have to be processed. <br />
Making all symbols hidden by default significantly reduces the size of the dynamic symbol table (faster<br />
lookup and smaller libraries). See http://gcc.gnu.org/wiki/Visibility<br />
and http://people.redhat.com/drepper/dsohowto.pdf for more details.<br />
<br />
Also making every symbol accessible can inadvertently cause ABI<br />
dependencies making it harder to maintain libraries.<br />
<br />
Furthermore, hiding functions by default enables much more aggressive compiler optimizations, to the benefit of both executable performance and code size. Some examples for this are elision of completely inlined functions, optimization of function signatures/calling conventions, partial inlining/constant propagation, … Some of these optimization opportunities also positively affect compile times, as evidenced by an experimental LDC patch (see [https://github.com/ldc-developers/ldc/pull/483 LDC #483], although LTO is required to fully exploit this).<br />
<br />
==Implementation Details==<br />
<br />
=== Windows ===<br />
<br />
==== Data Symbols ====<br />
<br />
===== Accessing through code =====<br />
<br />
For data symbols the 'export' attribute always means 'dllexport' when<br />
defining a symbol and 'dllimport' when accessing a symbol. That is<br />
accessing an exported variable is done through dereferencing it's<br />
corresponding import symbols. When defining an exported variable the<br />
compiler will emit a corresponding import symbol that is initialized<br />
with address of the variable. The import symbol can be located in the<br />
read only data segment. The mangling of the import symbol consists of<br />
the '_imp_'/'__imp_' (Win32/Win64) prefix followed by the mangled name<br />
of the variable. Import symbols itself are not exported. When an<br />
exported variable of the same module is accessed the compiler might<br />
avoid the indirection and perform a direct access.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export __gshared int var = 5;<br />
__gshared int* _imp__D1a3vari = &var; // import symbol generated by the compiler<br />
<br />
void func()<br />
{<br />
var = 3; // accesses var directly, because in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
var = 5; // accesses through indirection because var is marked as export and in a different module<br />
// *_imp__D1a3vari = 5; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
===== Referencing in constant data ======<br />
<br />
When referencing data symbols in the contents of some other data symbol there will be a additional level of indirection which needs to be removed during program startup.<br />
<br />
<syntaxhighlight lang=D><br />
module dll;<br />
<br />
__gshared int var = 5;<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=D><br />
module exe;<br />
import dll;<br />
<br />
__gshared int* pvar = &var; // address not known at compile time<br />
</syntaxhighlight><br />
<br />
As the address of var is not known at compile time so pvar will point to the entry in the import table for 'var'. At program startup, before any other D code runs, pvar will be dereferenced once. E.g. the following operation will be executed on pvar.<br />
<br />
<syntaxhighlight lang=D><br />
pvar = *cast(int**)pvar;<br />
</syntaxhighlight><br />
<br />
This removes the additional indirection added by the import table and correctly initializes the static memory for pvar. This might happen in various other cases, mostly when generating initializers, type infos, vtables, module infos and other static data the compiler produces.<br />
<br />
==== Function Symbols ====<br />
<br />
For function symbols the 'export' attribute always means 'dllexport'<br />
when defining a function and will be ignored when calling it.<br />
Calling an exported function is always done through the original symbol.<br />
In an import library the original symbol is defined as trampoline that simply calls the<br />
dereferenced _imp_ pointer.<br />
Thus calling an exported function will be compatible with both import<br />
libraries and static libraries, in the later case without indirection.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export void func()<br />
{<br />
}<br />
<br />
void bar()<br />
{<br />
func(); // call func; // directly<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
func(); // call func; // through trampoline<br />
}<br />
<br />
// definitions in the import library generated by implib<br />
void func()<br />
{<br />
asm<br />
{<br />
naked;<br />
jmp [_imp_func];<br />
}<br />
}<br />
void function() _imp_func = &func; // filled at runtime with the DLL address of func<br />
</syntaxhighlight><br />
<br />
==== TLS variables ====<br />
<br />
Note: This is not implemented at the moment.<br />
<br />
For each exported TLS variable the compiler should generate a function<br />
that returns the address of the TLS variable in the current<br />
thread. These internal methods should have some kind of unified prefix<br />
to mark them as TLS import helpers. I propose "__tlsstub_". These<br />
internal methods are also exported. So when accessing an exported TLS<br />
variable the compiler will insert a call to<br />
'_imp__D1a15__tlsstub_g_tlsFZPi' instead. As an optimization accesses<br />
to exported TLS variables within the same module can be performed<br />
directly.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export int g_tls = 5; // thread local storage<br />
<br />
export int* __tlsstub__g_tls() // generated by the compiler<br />
{<br />
return &g_tls;<br />
}<br />
alias _imp___tlsstub__g_tls = __tlsstub__g_tls; // also generated by the compiler<br />
<br />
void func()<br />
{<br />
g_tls = 3; // direct access because marked as export and in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
g_tls = 10; // access through _imp___tlsstub__g_tls function because marked as export and in a different module<br />
// *_imp___tlsstub__g_tls() = 10; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
=== *nix ===<br />
<br />
Note: This is not yet implemented.<br />
<br />
On *nix systems the default symbols visibility should be changed to<br />
hidden, i.e. -fvisibility=hidden argument of gcc. Only symbols marked<br />
with '''export''' should get the attribute visible.<br />
<br />
This is trivial to implement on GDC and LDC.<br />
<br />
=== Linking archives into shared libraries ===<br />
<br />
When linking archives into shared libraries the exported symbols from the archive will also be exported from the resulting shared library. Most often this is unwanted and may lead to inadvertent ABI dependencies.<br />
To accomplish this we'll provide a tool that strips export attributes from archives.<br />
<br />
== Copyright ==<br />
<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=3051DIP452013-10-27T09:20:21Z<p>Ingrater: /* Rationale */</p>
<hr />
<div>{| class="wikitable" <br />
!Title: <br />
!'''making export an attribute''' <br />
|-<br />
|DIP: <br />
|45 <br />
|- <br />
|Version: <br />
|2 <br />
|- <br />
|Status: <br />
|Draft <br />
|- <br />
|Created: <br />
|2013-08-27<br />
|- <br />
|Last Modified: <br />
|2013-09-06 <br />
|- <br />
|Author: <br />
|Benjamin Thaut, Martin Nowak <br />
|- <br />
|Links: <br />
|<br />
*http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
*http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
*http://d.puremagic.com/issues/show_bug.cgi?id=9816 <br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior need to be changed in serveral ways to make it<br />
work on Windows and allow better code generation for other<br />
plattforms. The Rationale section explains the problems and shows how<br />
this DIP solves them.<br />
<br />
==Description==<br />
<br />
* The '''export''' protection level should be turned into a '''export''' attribute.<br />
* If a module contains a single symbol annotated with the 'export' attribute all compiler internal symbols of this module should recieve the 'export' attribute too (e.g. module info). <br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute. <br />
* There should be only one meaning of 'export'. <br />
* It should be possible to access TLS variables across DLL / shared library boundaries. <br />
* On *nix systems default symbol visibility is changed to hidden, and only symbols marked with export become visible.<br />
* When compiling a static library with -lib all '''export''' attributes are ignored.<br />
* When passing object files to dmd the -lib flag will cause all exported symbols to be removed from the object files before invoking the linker.<br />
* A new compiler flag -libexports will be added to disable the previous behavior changes to -lib<br />
<br />
==Rationale==<br />
<br />
===Turning export into an attribute===<br />
<br />
Currently '''export''' is a protection level, the highest level of<br />
visibility actually. This however conflicts with the need to export<br />
'protected' symbols. Consider a Base class in a shared library.<br />
<br />
<syntaxhighlight lang=D> module sharedLib;<br />
<br />
class Base { <br />
protected final void doSomething() { ... } <br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D> module executable; import sharedLib;<br />
<br />
class Derived : Base { <br />
public void func() <br />
{ <br />
doSomething(); <br />
} <br />
}<br />
</syntaxhighlight><br />
<br />
In the above example 'doSomething' should only be visible to derived<br />
classes but it still needs to be exportable from a shared library.<br />
Therefor '''export''' should become a normal attribute which behaves<br />
orthogonal to protection.<br />
<br />
===Implicitly exporting compiler internal symbols===<br />
<br />
All compiler internal symbols need to be treated as exported if using<br />
an exported symbol might implicitly reference them to avoid link<br />
errors. The most prominent example is the ModuleInfo which needs<br />
linkage if the module has a ''static this()''.<br />
<br />
===export attribute inference===<br />
<br />
Currently export has to be specified in a lot of places to export all<br />
neccessary functions and data symbols. Export should be transitive in<br />
such a sense that it only needs to be specified once in a module to<br />
export all of its functions / data members including classes and their<br />
members / data symbols. Consider the following example:<br />
<br />
<syntaxhighlight lang=D> module sharedLib:<br />
<br />
export:<br />
<br />
__gshared int g_Var; // should be exported<br />
<br />
void globalFunc() { ... } // should be exported<br />
<br />
class A // compiler internal members should be exported <br />
{ <br />
private: <br />
int m_a;<br />
<br />
static int s_b; // should not be exported<br />
<br />
void internalFunc() { ... } // should not be exported<br />
<br />
protected: <br />
void interalFunc2() { ... } // should be exported<br />
<br />
public: <br />
class Inner // compiler internal members should be exported<br />
{ <br />
static s_inner; // should be exported<br />
<br />
void innerMethod() { ... } // should be exported <br />
}<br />
<br />
void method() { ... } // should be exported <br />
}<br />
<br />
private class C // should not be exported <br />
{ <br />
public void method() {... } // should not be exported <br />
} <br />
</syntaxhighlight><br />
<br />
===A single meaning of '''export'''===<br />
<br />
The classical solution to handle dllexport/dllimport attributes on<br />
Windows is to define a macro that depending on the current build<br />
setting expands to __declspec(dllexport) or to __declspec(dllimport).<br />
This complicates the build setup and means that object files for a<br />
static library can't be mixed well with object files for a DLL.<br />
Instead we propose that exported data definitions are accompanied with<br />
an _imp_ pointer and always accessed through them. See the<br />
implementation detail section for how this will work for<br />
[[#Data_Symbols|data symbols]] and [[#Function_Symbols|function<br />
symbols]]. That way a compiled object file can be used for a DLL or a<br />
static library. And vice versa an object file can be linked against an<br />
import library or a static library.<br />
<br />
===Access TLS variables===<br />
<br />
Currently it is not possible to access TLS variables across shared<br />
library boundaries on Windows. This should be implemented (see<br />
[[#TLS_variables|implementation details]] for a proposal).<br />
<br />
===Change symbol visibility on *nix systems===<br />
<br />
When building shared libraries on *nix systems all symbols are visible<br />
by default. This is a main reason for the performance impact of PIC<br />
because every data access and every function call go through the GOT<br />
or PLT indirection. It also leads to long loading time because an<br />
excessive number of relocations have to be processed. <br />
Making all symbols hidden by default significantly reduces the size of the dynamic symbol table (faster<br />
lookup and smaller libraries). See http://gcc.gnu.org/wiki/Visibility<br />
and http://people.redhat.com/drepper/dsohowto.pdf for more details.<br />
<br />
Also making every symbol accessible can inadvertently cause ABI<br />
dependencies making it harder to maintain libraries.<br />
<br />
===Changes to -lib dmd flag===<br />
<br />
When creating shared libraries, library creators usually want to commit to a certain interface. Strictly speaking this interface consits of every exported symbol from the library.<br />
If other third party libraries are linked statically into the shared library beeing created, the exported symbols from that third party library should not end up in the final<br />
shared library because they would become part of the interface. To accomplish this, the described changes to the -lib flag are necessary. The only exception, where this behaviour is actually wanted, is linking druntime into phobos. This case is special because phobos and druntime are merged into one big library. For this case the -libexports flag will be added.<br />
<br />
==Implementation Details==<br />
<br />
=== Windows ===<br />
<br />
==== Data Symbols ====<br />
<br />
For data symbols the 'export' attribute always means 'dllexport' when<br />
defining a symbol and 'dllimport' when accessing a symbol. That is<br />
accessing an exported variable is done through dereferencing it's<br />
corresponding import symbols. When defining an exported variable the<br />
compiler will emit a corresponding import symbol that is initialized<br />
with address of the variable. The import symbol can be located in the<br />
read only data segment. The mangling of the import symbol consists of<br />
the '_imp_'/'__imp_' (Win32/Win64) prefix followed by the mangled name<br />
of the variable. Import symbols itself are not exported. When an<br />
exported variable of the same module is accessed the compiler might<br />
avoid the indirection and perform a direct access.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export __gshared int var = 5;<br />
__gshared int* _imp__D1a3vari = &var; // import symbol generated by the compiler<br />
<br />
void func()<br />
{<br />
var = 3; // accesses var directly, because in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
var = 5; // accesses through indirection because var is marked as export and in a different module<br />
// *_imp__D1a3vari = 5; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
==== Function Symbols ====<br />
<br />
For function symbols the 'export' attribute always means 'dllexport'<br />
when defining a function and 'dllimport' when calling a function.<br />
Calling an exported function is always done through the original symbol.<br />
In an import library the original symbol is redifined as trampoline that simply<br />
dereferences the _imp_ pointer to the DLL function.<br />
Thus calling an exported function will be compatible with both import<br />
libraries and static libraries, in the later case without indirection.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export void func()<br />
{<br />
}<br />
<br />
void bar()<br />
{<br />
func(); // call func; // directly<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
func(); // call func; // through trampoline<br />
}<br />
<br />
// definitions in the import library generated by implib<br />
void func()<br />
{<br />
asm<br />
{<br />
naked;<br />
jmp [_imp_func];<br />
}<br />
}<br />
void function() _imp_func = &func; // filled at runtime with the DLL address of func<br />
</syntaxhighlight><br />
<br />
==== TLS variables ====<br />
<br />
For each exported TLS variable the compiler should generate a function<br />
that returns the address of the TLS variable in the current<br />
thread. These internal methods should have some kind of unified prefix<br />
to mark them as TLS import helpers. I propose "__tlsstub_". These<br />
internal methods are also exported. So when accessing an exported TLS<br />
variable the compiler will insert a call to<br />
'_imp__D1a15__tlsstub_g_tlsFZPi' instead. As an optimization accesses<br />
to exported TLS variables within the same module can be performed<br />
directly.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export int g_tls = 5; // thread local storage<br />
<br />
export int* __tlsstub__g_tls() // generated by the compiler<br />
{<br />
return &g_tls;<br />
}<br />
alias _imp___tlsstub__g_tls = __tlsstub__g_tls; // also generated by the compiler<br />
<br />
void func()<br />
{<br />
g_tls = 3; // direct access because marked as export and in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
g_tls = 10; // access through _imp___tlsstub__g_tls function because marked as export and in a different module<br />
// *_imp___tlsstub__g_tls() = 10; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
=== *nix ===<br />
<br />
On *nix systems the default symbols visibility should be changed to<br />
hidden, i.e. -fvisibility=hidden argument of gcc. Only symbols marked<br />
with '''export''' should get the attribute visible.<br />
<br />
== Copyright ==<br />
<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=3050DIP452013-10-27T09:15:07Z<p>Ingrater: /* Description */</p>
<hr />
<div>{| class="wikitable" <br />
!Title: <br />
!'''making export an attribute''' <br />
|-<br />
|DIP: <br />
|45 <br />
|- <br />
|Version: <br />
|2 <br />
|- <br />
|Status: <br />
|Draft <br />
|- <br />
|Created: <br />
|2013-08-27<br />
|- <br />
|Last Modified: <br />
|2013-09-06 <br />
|- <br />
|Author: <br />
|Benjamin Thaut, Martin Nowak <br />
|- <br />
|Links: <br />
|<br />
*http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
*http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
*http://d.puremagic.com/issues/show_bug.cgi?id=9816 <br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior need to be changed in serveral ways to make it<br />
work on Windows and allow better code generation for other<br />
plattforms. The Rationale section explains the problems and shows how<br />
this DIP solves them.<br />
<br />
==Description==<br />
<br />
* The '''export''' protection level should be turned into a '''export''' attribute.<br />
* If a module contains a single symbol annotated with the 'export' attribute all compiler internal symbols of this module should recieve the 'export' attribute too (e.g. module info). <br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute. <br />
* There should be only one meaning of 'export'. <br />
* It should be possible to access TLS variables across DLL / shared library boundaries. <br />
* On *nix systems default symbol visibility is changed to hidden, and only symbols marked with export become visible.<br />
* When compiling a static library with -lib all '''export''' attributes are ignored.<br />
* When passing object files to dmd the -lib flag will cause all exported symbols to be removed from the object files before invoking the linker.<br />
* A new compiler flag -libexports will be added to disable the previous behavior changes to -lib<br />
<br />
==Rationale==<br />
<br />
===Turning export into an attribute===<br />
<br />
Currently '''export''' is a protection level, the highest level of<br />
visibility actually. This however conflicts with the need to export<br />
'protected' symbols. Consider a Base class in a shared library.<br />
<br />
<syntaxhighlight lang=D> module sharedLib;<br />
<br />
class Base { <br />
protected final void doSomething() { ... } <br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D> module executable; import sharedLib;<br />
<br />
class Derived : Base { <br />
public void func() <br />
{ <br />
doSomething(); <br />
} <br />
}<br />
</syntaxhighlight><br />
<br />
In the above example 'doSomething' should only be visible to derived<br />
classes but it still needs to be exportable from a shared library.<br />
Therefor '''export''' should become a normal attribute which behaves<br />
orthogonal to protection.<br />
<br />
===Implicitly exporting compiler internal symbols===<br />
<br />
All compiler internal symbols need to be treated as exported if using<br />
an exported symbol might implicitly reference them to avoid link<br />
errors. The most prominent example is the ModuleInfo which needs<br />
linkage if the module has a ''static this()''.<br />
<br />
===export attribute inference===<br />
<br />
Currently export has to be specified in a lot of places to export all<br />
neccessary functions and data symbols. Export should be transitive in<br />
such a sense that it only needs to be specified once in a module to<br />
export all of its functions / data members including classes and their<br />
members / data symbols. Consider the following example:<br />
<br />
<syntaxhighlight lang=D> module sharedLib:<br />
<br />
export:<br />
<br />
__gshared int g_Var; // should be exported<br />
<br />
void globalFunc() { ... } // should be exported<br />
<br />
class A // compiler internal members should be exported <br />
{ <br />
private: <br />
int m_a;<br />
<br />
static int s_b; // should not be exported<br />
<br />
void internalFunc() { ... } // should not be exported<br />
<br />
protected: <br />
void interalFunc2() { ... } // should be exported<br />
<br />
public: <br />
class Inner // compiler internal members should be exported<br />
{ <br />
static s_inner; // should be exported<br />
<br />
void innerMethod() { ... } // should be exported <br />
}<br />
<br />
void method() { ... } // should be exported <br />
}<br />
<br />
private class C // should not be exported <br />
{ <br />
public void method() {... } // should not be exported <br />
} <br />
</syntaxhighlight><br />
<br />
===A single meaning of '''export'''===<br />
<br />
The classical solution to handle dllexport/dllimport attributes on<br />
Windows is to define a macro that depending on the current build<br />
setting expands to __declspec(dllexport) or to __declspec(dllimport).<br />
This complicates the build setup and means that object files for a<br />
static library can't be mixed well with object files for a DLL.<br />
Instead we propose that exported data definitions are accompanied with<br />
an _imp_ pointer and always accessed through them. See the<br />
implementation detail section for how this will work for<br />
[[#Data_Symbols|data symbols]] and [[#Function_Symbols|function<br />
symbols]]. That way a compiled object file can be used for a DLL or a<br />
static library. And vice versa an object file can be linked against an<br />
import library or a static library.<br />
<br />
===Access TLS variables===<br />
<br />
Currently it is not possible to access TLS variables across shared<br />
library boundaries on Windows. This should be implemented (see<br />
[[#TLS_variables|implementation details]] for a proposal).<br />
<br />
===Change symbol visibility on *nix systems===<br />
<br />
When building shared libraries on *nix systems all symbols are visible<br />
by default. This is a main reason for the performance impact of PIC<br />
because every data access and every function call go through the GOT<br />
or PLT indirection. It also leads to long loading time because an<br />
excessive number of relocations have to be processed. <br />
Making all symbols hidden by default significantly reduces the size of the dynamic symbol table (faster<br />
lookup and smaller libraries). See http://gcc.gnu.org/wiki/Visibility<br />
and http://people.redhat.com/drepper/dsohowto.pdf for more details.<br />
<br />
Also making every symbol accessible can inadvertently cause ABI<br />
dependencies making it harder to maintain libraries.<br />
<br />
==Implementation Details==<br />
<br />
=== Windows ===<br />
<br />
==== Data Symbols ====<br />
<br />
For data symbols the 'export' attribute always means 'dllexport' when<br />
defining a symbol and 'dllimport' when accessing a symbol. That is<br />
accessing an exported variable is done through dereferencing it's<br />
corresponding import symbols. When defining an exported variable the<br />
compiler will emit a corresponding import symbol that is initialized<br />
with address of the variable. The import symbol can be located in the<br />
read only data segment. The mangling of the import symbol consists of<br />
the '_imp_'/'__imp_' (Win32/Win64) prefix followed by the mangled name<br />
of the variable. Import symbols itself are not exported. When an<br />
exported variable of the same module is accessed the compiler might<br />
avoid the indirection and perform a direct access.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export __gshared int var = 5;<br />
__gshared int* _imp__D1a3vari = &var; // import symbol generated by the compiler<br />
<br />
void func()<br />
{<br />
var = 3; // accesses var directly, because in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
var = 5; // accesses through indirection because var is marked as export and in a different module<br />
// *_imp__D1a3vari = 5; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
==== Function Symbols ====<br />
<br />
For function symbols the 'export' attribute always means 'dllexport'<br />
when defining a function and 'dllimport' when calling a function.<br />
Calling an exported function is always done through the original symbol.<br />
In an import library the original symbol is redifined as trampoline that simply<br />
dereferences the _imp_ pointer to the DLL function.<br />
Thus calling an exported function will be compatible with both import<br />
libraries and static libraries, in the later case without indirection.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export void func()<br />
{<br />
}<br />
<br />
void bar()<br />
{<br />
func(); // call func; // directly<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
func(); // call func; // through trampoline<br />
}<br />
<br />
// definitions in the import library generated by implib<br />
void func()<br />
{<br />
asm<br />
{<br />
naked;<br />
jmp [_imp_func];<br />
}<br />
}<br />
void function() _imp_func = &func; // filled at runtime with the DLL address of func<br />
</syntaxhighlight><br />
<br />
==== TLS variables ====<br />
<br />
For each exported TLS variable the compiler should generate a function<br />
that returns the address of the TLS variable in the current<br />
thread. These internal methods should have some kind of unified prefix<br />
to mark them as TLS import helpers. I propose "__tlsstub_". These<br />
internal methods are also exported. So when accessing an exported TLS<br />
variable the compiler will insert a call to<br />
'_imp__D1a15__tlsstub_g_tlsFZPi' instead. As an optimization accesses<br />
to exported TLS variables within the same module can be performed<br />
directly.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export int g_tls = 5; // thread local storage<br />
<br />
export int* __tlsstub__g_tls() // generated by the compiler<br />
{<br />
return &g_tls;<br />
}<br />
alias _imp___tlsstub__g_tls = __tlsstub__g_tls; // also generated by the compiler<br />
<br />
void func()<br />
{<br />
g_tls = 3; // direct access because marked as export and in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
g_tls = 10; // access through _imp___tlsstub__g_tls function because marked as export and in a different module<br />
// *_imp___tlsstub__g_tls() = 10; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
=== *nix ===<br />
<br />
On *nix systems the default symbols visibility should be changed to<br />
hidden, i.e. -fvisibility=hidden argument of gcc. Only symbols marked<br />
with '''export''' should get the attribute visible.<br />
<br />
== Copyright ==<br />
<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2948DIP452013-09-06T07:08:50Z<p>Ingrater: </p>
<hr />
<div>{| class="wikitable" <br />
!Title: <br />
!'''making export an attribute''' <br />
|-<br />
|DIP: <br />
|45 <br />
|- <br />
|Version: <br />
|2 <br />
|- <br />
|Status: <br />
|Draft <br />
|- <br />
|Created: <br />
|2013-08-27<br />
|- <br />
|Last Modified: <br />
|2013-09-06 <br />
|- <br />
|Author: <br />
|Benjamin Thaut, Martin Nowak <br />
|- <br />
|Links: <br />
|<br />
*http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
*http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
*http://d.puremagic.com/issues/show_bug.cgi?id=9816 <br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior need to be changed in serveral ways to make it<br />
work on Windows and allow better code generation for other<br />
plattforms. The Rationale section explains the problems and shows how<br />
this DIP solves them.<br />
<br />
==Description==<br />
<br />
* The '''export''' protection level should be turned into a '''export''' attribute.<br />
* If a module contains a single symbol annotated with the 'export' attribute all compiler internal symbols of this module should recieve the 'export' attribute too (e.g. module info). <br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute. <br />
* There should be only one meaning of 'export'. <br />
* It should be possible to access TLS variables across DLL / shared library boundaries. <br />
* On *nix systems default symbol visibility is changed to hidden, and only symbols marked with export become visible.<br />
<br />
==Rationale==<br />
<br />
===Turning export into an attribute===<br />
<br />
Currently '''export''' is a protection level, the highest level of<br />
visibility actually. This however conflicts with the need to export<br />
'protected' symbols. Consider a Base class in a shared library.<br />
<br />
<syntaxhighlight lang=D> module sharedLib;<br />
<br />
class Base { <br />
protected final void doSomething() { ... } <br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D> module executable; import sharedLib;<br />
<br />
class Derived : Base { <br />
public void func() <br />
{ <br />
doSomething(); <br />
} <br />
}<br />
</syntaxhighlight><br />
<br />
In the above example 'doSomething' should only be visible to derived<br />
classes but it still needs to be exportable from a shared library.<br />
Therefor '''export''' should become a normal attribute which behaves<br />
orthogonal to protection.<br />
<br />
===Implicitly exporting compiler internal symbols===<br />
<br />
All compiler internal symbols need to be treated as exported if using<br />
an exported symbol might implicitly reference them to avoid link<br />
errors. The most prominent example is the ModuleInfo which needs<br />
linkage if the module has a ''static this()''.<br />
<br />
===export attribute inference===<br />
<br />
Currently export has to be specified in a lot of places to export all<br />
neccessary functions and data symbols. Export should be transitive in<br />
such a sense that it only needs to be specified once in a module to<br />
export all of its functions / data members including classes and their<br />
members / data symbols. Consider the following example:<br />
<br />
<syntaxhighlight lang=D> module sharedLib:<br />
<br />
export:<br />
<br />
__gshared int g_Var; // should be exported<br />
<br />
void globalFunc() { ... } // should be exported<br />
<br />
class A // compiler internal members should be exported <br />
{ <br />
private: <br />
int m_a;<br />
<br />
static int s_b; // should not be exported<br />
<br />
void internalFunc() { ... } // should not be exported<br />
<br />
protected: <br />
void interalFunc2() { ... } // should be exported<br />
<br />
public: <br />
class Inner // compiler internal members should be exported<br />
{ <br />
static s_inner; // should be exported<br />
<br />
void innerMethod() { ... } // should be exported <br />
}<br />
<br />
void method() { ... } // should be exported <br />
}<br />
<br />
private class C // should not be exported <br />
{ <br />
public void method() {... } // should not be exported <br />
} <br />
</syntaxhighlight><br />
<br />
===A single meaning of '''export'''===<br />
<br />
The classical solution to handle dllexport/dllimport attributes on<br />
Windows is to define a macro that depending on the current build<br />
setting expands to __declspec(dllexport) or to __declspec(dllimport).<br />
This complicates the build setup and means that object files for a<br />
static library can't be mixed well with object files for a DLL.<br />
Instead we propose that export symbols are accompanied with weak<br />
import aliases and always accessed through them. See the<br />
implementation detail section for how this will work for<br />
[[#Data_Symbols|data symbols]] and [[#Function_Symbols|function<br />
symbols]]. That way a compiled object file can be used for a DLL or a<br />
static library. And vice versa an object file can be linked against an<br />
import library or a static library.<br />
<br />
===Access TLS variables===<br />
<br />
Currently it is not possible to access TLS variables across shared<br />
library boundaries on Windows. This should be implemented (see<br />
[[#TLS_variables|implementation details]] for a proposal).<br />
<br />
===Change symbol visibility on *nix systems===<br />
<br />
When building shared libraries on *nix systems all symbols are visible<br />
by default. This is a main reason for the performance impact of PIC<br />
because every data access and every function call go through the GOT<br />
or PLT indirection. It also leads to long loading time because an<br />
excessive number of relocations have to be processed. <br />
Making all symbols hidden by default significantly reduces the size of the dynamic symbol table (faster<br />
lookup and smaller libraries). See http://gcc.gnu.org/wiki/Visibility<br />
and http://people.redhat.com/drepper/dsohowto.pdf for more details.<br />
<br />
Also making every symbol accessible can inadvertently cause ABI<br />
dependencies making it harder to maintain libraries.<br />
<br />
==Implementation Details==<br />
<br />
=== Windows ===<br />
<br />
==== Data Symbols ====<br />
<br />
For data symbols the 'export' attribute always means 'dllexport' when<br />
defining a symbol and 'dllimport' when accessing a symbol. That is<br />
accessing an exported variable is done through dereferencing it's<br />
corresponding import symbols. When defining an exported variable the<br />
compiler will emit a corresponding import symbol that is initialized<br />
with address of the variable. The import symbol can be located in the<br />
read only data segment. The mangling of the import symbol consists of<br />
the '_imp_'/'__imp_' (Win32/Win64) prefix followed by the mangled name<br />
of the variable. Import symbols itself are not exported. When an<br />
exported variable of the same module is accessed the compiler might<br />
avoid the indirection and perform a direct access.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export __gshared int var = 5;<br />
__gshared int* _imp__D1a3vari = &var; // import symbol generated by the compiler<br />
<br />
void func()<br />
{<br />
var = 3; // accesses var directly, because in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
var = 5; // accesses through indirection because var is marked as export and in a different module<br />
// *_imp__D1a3vari = 5; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
==== Function Symbols ====<br />
<br />
For function symbols the 'export' attribute always means 'dllexport'<br />
when defining a function and 'dllimport' when calling a function.<br />
That is calling an exported function is done through it's<br />
corresponding import symbol. When defining an exported function the<br />
compiler will emit a corresponding import symbols that is an alias to<br />
the function (See [http://blog.omega-prime.co.uk/?p=121#windows COFF weak externals]<br />
and [http://www.azillionmonkeys.com/qed/Omfg.pdf OMF ALIAS record]<br />
on how to implement aliases). Thus calling an exported<br />
function becomes compatible with both import libraries and static<br />
libraries, in the later case without indirection.<br />
<br />
==== TLS variables ====<br />
<br />
For each exported TLS variable the compiler should generate a function<br />
that returns the address of the TLS variable in the current<br />
thread. These internal methods should have some kind of unified prefix<br />
to mark them as TLS import helpers. I propose "__tlsstub_". These<br />
internal methods are also exported. So when accessing an exported TLS<br />
variable the compiler will insert a call to<br />
'_imp__D1a15__tlsstub_g_tlsFZPi' instead. As an optimization accesses<br />
to exported TLS variables within the same module can be performed<br />
directly.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
<br />
export int g_tls = 5; // thread local storage<br />
<br />
export int* __tlsstub__g_tls() // generated by the compiler<br />
{<br />
return &g_tls;<br />
}<br />
alias _imp___tlsstub__g_tls = __tlsstub__g_tls; // also generated by the compiler<br />
<br />
void func()<br />
{<br />
g_tls = 3; // direct access because marked as export and in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
g_tls = 10; // access through _imp___tlsstub__g_tls function because marked as export and in a different module<br />
// *_imp___tlsstub__g_tls() = 10; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
=== *nix ===<br />
<br />
On *nix systems the default symbols visibility should be changed to<br />
hidden, i.e. -fvisibility=hidden argument of gcc. Only symbols marked<br />
with '''export''' should get the attribute visible.<br />
<br />
== Copyright ==<br />
<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2942DIP452013-09-01T19:39:45Z<p>Ingrater: </p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''making export an attribute'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-09-01<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|<br />
*http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
*http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
*http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior need to be changed in serveral ways to make it work on Windows and allow better code generation for other plattforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
* The 'export' protection level should be turned into a 'export' attribute.<br />
* If a module contains a single symbol annotated with the 'export' attribute all compiler internal symbols of this module should recieve the 'export' attribute too (e.g. module info).<br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute.<br />
* It should be possible to access TLS variables across DLL / shared library boundaries.<br />
* On *nix systems default symbol visibility is changed to hidden, and only with export marked symbols are visible.<br />
<br />
==Rationale==<br />
<br />
===Turning export into an attribute===<br />
<br />
Currently the export protection level is the highest level of visibility. This however does not allow exporting protected members. Exporting protected members is neccessary sometimes though.<br />
Consider the following example.<br />
<br />
<syntaxhighlight lang=D><br />
module sharedLib;<br />
<br />
class Base<br />
{<br />
protected final void DoSomething() { ... }<br />
<br />
public void func()<br />
{<br />
DoSomething();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module executable;<br />
import sharedLib;<br />
<br />
class Derived<br />
{<br />
protected final void DoSomethingAdditional() { ... }<br />
<br />
public ovveride void func()<br />
{<br />
DoSomething();<br />
DoSomethingAdditional();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
In the above example 'DoSomething' should only be visible to derived classes but should still be exported from a shared library otherwise it will lead to a linker error. This does not work with the current implementation of 'export'. Turning 'export' into an attribute will make this work.<br />
<br />
===Implicitly exporting compiler internal symbols of a module===<br />
<br />
Currently compiler internal symbols of modules are not exported at all. This leads to linker errors when linking against shared libraries on windows. By marking compiler internal symbols as 'export' as soon as there is a single exported symbol in the module will fix this problem.<br />
<br />
===export attribute inferrence===<br />
<br />
Currently export has to be specified in a lot of places to export all neccessary functions and data symbols. Export should be transitive in such a sense that it only needs to be specified once in a module to export all of its functions / data members including classes and their members / data symbols. Consider the following example:<br />
<br />
<syntaxhighlight lang=D><br />
module sharedLib:<br />
<br />
export:<br />
<br />
__gshared int g_Var; // should be exported<br />
<br />
void globalFunc() { ... } // should be exported<br />
<br />
class A // compiler internal members should be exported<br />
{<br />
private:<br />
int m_a;<br />
<br />
static int s_b; // should not be exported<br />
<br />
void internalFunc() { ... } // should not be exported<br />
<br />
protected:<br />
void interalFunc2() { ... } // should be exported<br />
<br />
public:<br />
class Inner // compiler internal members should be exported<br />
{<br />
static s_inner; // should be exported<br />
<br />
void innerMethod() { ... } // should be exported<br />
}<br />
<br />
void method() { ... } // should be exported<br />
}<br />
<br />
private class C // should not be exported<br />
{<br />
public void method() { ... } // should not be exported<br />
}<br />
</syntaxhighlight><br />
<br />
===Access TLS variables===<br />
<br />
Currently it is not possible to access TLS variables across shared library boundaries. This should be implemented. See implementation details.<br />
<br />
===Change symbol visibility on *nix systems===<br />
<br />
When building shared libraries on *nix systems all symbols are visible by default. This can lead to long loading time of shared libraries if they contain a large number of symbols.<br />
Also everything visible by deafult makes it hard to commit to a certain stable interface, as one has no control over the visible symbols.<br />
<br />
==Implementation Details==<br />
<br />
=== Windows ===<br />
<br />
==== Data Symbols ====<br />
<br />
For data symbols the 'export' attribute always means 'dllexport' when compiling a module and always 'dllimport' when importing a module. When compiling a module the compiler will generate a import symbol containing the address of the data symbol for each data symbol it encounters. The mangling of the import symbol should be the same as that of the symbol it referes to with a additional prefix. This prefix is '_imp_' on windows 32-bit and '__imp_' on windows 64-bit. So if the data symbol's mangling is '_D5ivar' the import symbol mangling is '_imp__D5ivar' on 32-bit and '__imp__D5ivar' on 64-bit. The import symbol should NOT be expoted to avoid a conflict with the import symbols which are generated within the import library by the linker.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
export __gshared int var = 5;<br />
__gshared int* _imp_var = &var; // import symbol generated by the compiler<br />
<br />
void func()<br />
{<br />
var = 3; // accesses var directly, because in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
var = 5; // accesses var through the _imp_var indirection because var is marked as export and is located in a different module<br />
// *_imp_var = 5; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
When accessing data symbols which are marked with 'export' the access should always be done through the additional level of indirection using the import symbol unless the data symbol is located within the same module currently beeing compiled. Access through data symbols not marked with 'export' does not change in any way.<br />
<br />
==== Function Symbols ====<br />
<br />
For function symbols the 'export' attribute always means 'dllexport' when compiling a module and 'export' always equals a no-op when importing a module. Because the import library will generate method stubs with the correct symbol names function symbols can be called normally no matter if they are imported from a shared library or linked in from a static library.<br />
<br />
==== TLS variables ====<br />
<br />
On windows plattforms the compiler should generate a internal method for each TLS variable returing the addess of the TLS variable. These internal methods should have some kind of unified prefix to mark them as TLS import helpers. I propose "__access_tls_". These internal methods should also be exported from a shared library implicitly.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
export int g_tls = 5; // thread local storage<br />
<br />
export int* __access_tls_g_tls() // generated by the compiler<br />
{<br />
return &g_tls;<br />
}<br />
<br />
void func()<br />
{<br />
g_tls = 3; // direct access because marked as export and in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
g_tls = 10; // access through __access_tls_g_tls function because marked as export and in a imported module<br />
// *__access_tls_g_tls() = 10; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
When accessing a TLS variable marked with export and located within the same module currently compiled direct access should be done. When accessing a TLS variable marked with export from a imported module the access should be going through a additional indirection using __access_tls_ helper function.<br />
<br />
=== *nix ===<br />
<br />
On *nix systems the default symbols visibility needs to be changed to hidden and only symbols marked with 'export' should be visible when compiling a shared library.<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2941DIP452013-09-01T09:48:49Z<p>Ingrater: </p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''making export an attribute'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-09-01<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|<br />
*http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
*http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
*http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior need to be changed in serveral ways to make it work on Windows and allow better code generation for other plattforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
* The 'export' protection level should be turned into a 'export' attribute.<br />
* If a module contains a single symbol annotated with the 'export' attribute all compiler internal symbols of this module should recieve the 'export' attribute too (e.g. module info).<br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute.<br />
* It should be possible to access TLS variables across DLL / shared library boundaries.<br />
* On *nix systems default symbol visibility is changed to hidden, and only with export marked symbols are visible.<br />
<br />
==Rationale==<br />
<br />
===Turning export into an attribute===<br />
<br />
Currently the export protection level is the highest level of visibility. This however does not allow exporting protected members. Exporting protected members is neccessary sometimes though.<br />
Consider the following example.<br />
<br />
<syntaxhighlight lang=D><br />
module sharedLib;<br />
<br />
class Base<br />
{<br />
protected final void DoSomething() { ... }<br />
<br />
public void func()<br />
{<br />
DoSomething();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module executable;<br />
import sharedLib;<br />
<br />
class Derived<br />
{<br />
protected final void DoSomethingAdditional() { ... }<br />
<br />
public ovveride void func()<br />
{<br />
DoSomething();<br />
DoSomethingAdditional();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
In the above example 'DoSomething' should only be visible to derived classes but should still be exported from a shared library otherwise it will lead to a linker error. This does not work with the current implementation of 'export'. Turning 'export' into an attribute will make this work.<br />
<br />
===Implicitly exporting compiler internal symbols of a module===<br />
<br />
Currently compiler internal symbols of modules are not exported at all. This leads to linker errors when linking against shared libraries on windows. By marking compiler internal symbols as 'export' as soon as there is a single exported symbol in the module will fix this problem.<br />
<br />
===export attribute inferrence===<br />
<br />
Currently export has to be specified in a lot of places to export all neccessary functions and data symbols. Export should be transitive in such a sense that it only needs to be specified once in a module to export all of its functions / data members including classes and their members / data symbols. Consider the following example:<br />
<br />
<syntaxhighlight lang=D><br />
module sharedLib:<br />
<br />
export:<br />
<br />
__gshared int g_Var; // should be exported<br />
<br />
void globalFunc() { ... } // should be exported<br />
<br />
class A // compiler internal members should be exported<br />
{<br />
private:<br />
int m_a;<br />
<br />
static int s_b; // should not be exported<br />
<br />
void internalFunc() { ... } // should not be exported<br />
<br />
protected:<br />
void interalFunc2() { ... } // should be exported<br />
<br />
public:<br />
class Inner // compiler internal members should be exported<br />
{<br />
static s_inner; // should be exported<br />
<br />
void innerMethod() { ... } // should be exported<br />
}<br />
<br />
void method() { ... } // should be exported<br />
}<br />
<br />
private class C // should not be exported<br />
{<br />
public void method() { ... } // should not be exported<br />
}<br />
</syntaxhighlight><br />
<br />
===Access TLS variables===<br />
<br />
Currently it is not possible to access TLS variables across shared library boundaries. This should be implemented. See implementation details.<br />
<br />
===Change symbol visibility on *nix systems===<br />
<br />
When building shared libraries on *nix systems all symbols are visible by default. This can lead to long loading time of shared libraries if they contain a large number of symbols.<br />
Also everything visible by deafult makes it hard to commit to a certain stable interface, as one has no control over the visible symbols.<br />
<br />
==Implementation Details==<br />
<br />
=== Windows ===<br />
<br />
==== Data Symbols ====<br />
<br />
For data symbols the 'export' attribute always means 'dllexport' when compiling a module and always 'dllimport' when importing a module. When compiling a module the compiler will generate a import symbol containing the address of the data symbol for each data symbol it encounters. The mangling of the import symbol should be the same as that of the symbol it referes to with a additional prefix. This prefix is '_imp_' on windows 32-bit and '__imp_' on windows 64-bit. So if the data symbol's mangling is '_D5ivar' the import symbol mangling is '_imp__D5ivar' on 32-bit and '__imp__D5ivar' on 64-bit. The import symbol should NOT be expoted to avoid a conflict with the import symbols which are generated within the import library by the linker.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
export __gshared int var = 5;<br />
__gshared int* _imp_var = &var; // import symbol generated by the compiler<br />
<br />
void func()<br />
{<br />
var = 3; // accesses var directly, because in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
var = 5; // accesses var through the _imp_var indirection because var is marked as export and is located in a different module<br />
// *_imp_var = 5; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
When accessing data symbols which are marked with 'export' the access should always be done through the additional level of indirection using the import symbol unless the data symbol is located within the same module currently beeing compiled. Access through data symbols not marked with 'export' does not change in any way.<br />
<br />
==== Function Symbols ====<br />
<br />
For function symbols the 'export' attribute always means 'dllexport' when compiling a module and 'export' always equals a no-op when importing a module. Because the import library will generate method stubs with the correct symbol names function symbols can be called normally no matter if they are imported from a shared library or linked in from a static library.<br />
<br />
=== *nix ===<br />
<br />
On *nix systems the default symbols visibility needs to be changed to hidden and only symbols marked with 'export' should be visible when compiling a shared library.<br />
<br />
=== TLS variables ===<br />
<br />
For each TLS variable the compiler should generate a internal method returing the addess of the TLS variable. These internal methods should have some kind of unified prefix to mark them as TLS import helpers. I propose "__access_tls_". These internal methods should also be exported from a shared library implicitly.<br />
<br />
<syntaxhighlight lang=D><br />
module a;<br />
export int g_tls = 5; // thread local storage<br />
<br />
export int* __access_tls_g_tls() // generated by the compiler<br />
{<br />
return &g_tls;<br />
}<br />
<br />
void func()<br />
{<br />
g_tls = 3; // direct access because marked as export and in the same module<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module b;<br />
import a;<br />
<br />
void bar()<br />
{<br />
g_tls = 10; // access through __access_tls_g_tls function because marked as export and in a imported module<br />
// *__access_tls_g_tls() = 10; // code generated by the compiler<br />
}<br />
</syntaxhighlight><br />
<br />
When accessing a TLS variable marked with export and located within the same module currently compiled direct access should be done. When accessing a TLS variable marked with export from a imported module the access should be going through a additional indirection using __access_tls_ helper function.<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2940DIP452013-09-01T09:22:23Z<p>Ingrater: </p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''making export an attribute'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-08-30<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior needs to be changed in serveral ways to make it work on Windows and allow better code generation for other plattforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
* The 'export' protection level should be turned into a 'export' attribute.<br />
* If a module contains a single symbol annotated with the 'export' attribute all compiler internal symbols of this module should recieve the 'export' attribute too (e.g. module info).<br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute.<br />
* It should be possible to access TLS variables across DLL / shared library boundaries.<br />
* On *nix systems default symbol visibility is changed to hidden, and only with export marked symbols are visible.<br />
<br />
==Rationale==<br />
<br />
===Turning export into an attribute===<br />
<br />
Currently the export protection level is the highest level of visibility. This however does not allow exporting protected members. Exported protected members is neccessary sometimes though.<br />
Consider the following example.<br />
<br />
<syntaxhighlight lang=D><br />
module sharedLib;<br />
<br />
class Base<br />
{<br />
protected final void DoSomething() { ... }<br />
<br />
public void func()<br />
{<br />
DoSomething();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module executable;<br />
import sharedLib;<br />
<br />
class Derived<br />
{<br />
protected final void DoSomethingAdditional() { ... }<br />
<br />
public ovveride void func()<br />
{<br />
DoSomething();<br />
DoSomethingAdditional();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
In the above example 'DoSomething' should only be visible to derived classes but should still be exported from a shared library. This does not work with the current implementation of 'export'. Turning 'export' into an attribute will make this work.<br />
<br />
===Implicitly exporting compiler internal symbols of a module===<br />
<br />
Currently compiler internal symbols of modules are not exported at all. This leads to liner errors when linking against shared libraries on windows. By marking compiler internal symbols as 'export' as soon as there is a single exported symbol in the module will fix this problem.<br />
<br />
===export attribute inferrence===<br />
<br />
Currently export has to be specified in a lot of places to export all neccessary functions and data symbols. Export should be transitive in such a sense that it only needs to be specified once in a module to export all of its functions / data members including classes and their members / data symbols. Consider the following example:<br />
<br />
<syntaxhighlight lang=D><br />
module sharedLib:<br />
<br />
export:<br />
<br />
__gshared int g_Var; // should be exported<br />
<br />
void globalFunc() { ... } // should be exported<br />
<br />
class A // compiler internal members should be exported<br />
{<br />
private:<br />
int m_a;<br />
<br />
static int s_b; // should not be exported<br />
<br />
void internalFunc() { ... } // should not be exported<br />
<br />
protected:<br />
void interalFunc2() { ... } // should be exported<br />
<br />
public:<br />
class Inner // compiler internal members should be exported<br />
{<br />
static s_inner; // should be exported<br />
<br />
void innerMethod() { ... } // should be exported<br />
}<br />
<br />
void method() { ... } // should be exported<br />
}<br />
<br />
private class C // should not be exported<br />
{<br />
public void method() { ... } // should not be exported<br />
}<br />
</syntaxhighlight><br />
<br />
===Access TLS variables===<br />
<br />
Currently it is not possible to acces TLS variables across shared library boundaries. This should be implemented. See implementation details.<br />
<br />
===Change symbol visibility on *nix systems===<br />
<br />
When building shared libraries on *nix systems all symbols are visible by default. This can lead to long loading time of shared libraries if they contain a large number of symbols.<br />
Also everything visible by deafult makes it hard to commit to a certain stable interface, as one has no control over the visible symbols.<br />
<br />
==Implementation Details==<br />
<br />
=== Windows ===<br />
<br />
<br />
<br />
=== *nix ===<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2938DIP452013-09-01T09:07:14Z<p>Ingrater: /* Rationale */</p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''making export an attribute'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-08-30<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior needs to be changed in serveral ways to make it work on Windows and allow better code generation for other plattforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
* The 'export' protection level should be turned into a 'export' attribute.<br />
* If a module contains a single symbol annotated with the 'export' attribute all compiler internal symbols of this module should recieve the 'export' attribute too (e.g. module info).<br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute.<br />
* It should be possible to access TLS variables across DLL / shared library boundaries.<br />
* On *nix systems default symbol visibility is changed to hidden, and only with export marked symbols are visible.<br />
<br />
==Rationale==<br />
<br />
===Turning export into an attribute===<br />
<br />
Currently the export protection level is the highest level of visibility. This however does not allow exporting protected members. Exported protected members is neccessary sometimes though.<br />
Consider the following example.<br />
<br />
<syntaxhighlight lang=D><br />
module sharedLib;<br />
<br />
class Base<br />
{<br />
protected final void DoSomething() { ... }<br />
<br />
public void func()<br />
{<br />
DoSomething();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module executable;<br />
import sharedLib;<br />
<br />
class Derived<br />
{<br />
protected final void DoSomethingAdditional() { ... }<br />
<br />
public ovveride void func()<br />
{<br />
DoSomething();<br />
DoSomethingAdditional();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
In the above example 'DoSomething' should only be visible to derived classes but should still be exported from a shared library. This does not work with the current implementation of 'export'. Turning 'export' into an attribute will make this work.<br />
<br />
==Implementation Details==<br />
<br />
Work in progress<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2937DIP452013-09-01T08:59:19Z<p>Ingrater: /* Description */</p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''making export an attribute'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-08-30<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior needs to be changed in serveral ways to make it work on Windows and allow better code generation for other plattforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
* The 'export' protection level should be turned into a 'export' attribute.<br />
* If a module contains a single symbol annotated with the 'export' attribute all compiler internal symbols of this module should recieve the 'export' attribute too (e.g. module info).<br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute.<br />
* It should be possible to access TLS variables across DLL / shared library boundaries.<br />
* On *nix systems default symbol visibility is changed to hidden, and only with export marked symbols are visible.<br />
<br />
==Rationale==<br />
<br />
Work in progress<br />
<br />
==Implementation Details==<br />
<br />
Work in progress<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIPs&diff=2934DIPs2013-08-30T15:49:23Z<p>Ingrater: </p>
<hr />
<div>{| class="wikitable sortable"<br />
! ID<br />
! Title<br />
! Status<br />
! Description<br />
|-<br />
| [[DIP1]]<br />
| Template DIP<br />
| Draft<br />
| This is a DIP template that can be used as a model to start a new proposal.<br />
|-<br />
| [[DIP2]]<br />
| Const code bloat<br />
| '''Approved'''<br />
| proposed solution for [http://d.puremagic.com/issues/show_bug.cgi?id=1961 bug 1961].<br />
|-<br />
| [[DIP3]]<br />
| Remove inheritance protection<br />
| '''Approved'''<br />
| non-public inheritance in a single inheritance language that has a single root object hierarchy makes little sense.<br />
|-<br />
| [[DIP4]]<br />
| Properties<br />
| [[DIP6|Superseded by DIP6]]<br />
| an alternate usage/definition syntax for properties.<br />
|-<br />
| [[DIP5]]<br />
| Properties 2<br />
| [[DIP6|Superseded by DIP6]]<br />
| a variant of DIP4.<br />
|-<br />
| [[DIP6]]<br />
| Annotations<br />
| '''Approved'''<br />
| extend the D programming language with annotations.<br />
|-<br />
| [[DIP7]]<br />
| Operator overloading<br />
| '''Approved'''<br />
| Revamped operator overloading.<br />
|-<br />
| [[DIP8]]<br />
| Improving Runtime Type Info<br />
| Draft<br />
| Templating RTTI.<br />
|-<br />
| [[DIP9]]<br />
| Redo toString API<br />
| Draft<br />
| Replace inefficient aggregate toString API with efficient delegate-based version that supports formatting.<br />
|-<br />
| [[DIP10]]<br />
| Qualified constructors and destructors for structs<br />
| Draft<br />
|<br />
|-<br />
| [[DIP11]]<br />
| Automatic downloading of imports<br />
| Draft<br />
| Support automatically downloading imported files via new import path specifications or pragmas.<br />
|-<br />
| [[DIP12]]<br />
| C API Headers<br />
| '''Approved'''<br />
| Collection of D headers for common C libraries.<br />
|-<br />
| [[DIP13]]<br />
| Import path binding<br />
| Draft<br />
| Allow to bind an import path to a package.<br />
|-<br />
| [[DIP14]]<br />
| Import path binding in source code<br />
| Draft<br />
| Allow to bind an import path to a package from within sources.<br />
|-<br />
| [[DIP15]]<br />
| Import of packages<br />
| [[DIP37|Superseded by DIP37]]<br />
| Improve imports of packages with submodules.<br />
|-<br />
| [[DIP16]]<br />
| Transparently substitute module with package<br />
| [[DIP37|Superseded by DIP37]]<br />
|<br />
|-<br />
| [[DIP17]]<br />
| Sane volatile statement<br />
| [[DIP20|Superseded by DIP20]]<br />
|<br />
|-<br />
| [[DIP18]]<br />
| Non-GC Threads<br />
| Draft<br />
|<br />
|-<br />
| [[DIP20]]<br />
| Volatile read/write intrinsics<br />
| Draft<br />
| Intrinsics to perform C-style volatile loads/stores from/to memory.<br />
|-<br />
| [[DIP21]]<br />
| Fixing property<br />
| Draft<br />
|<br />
|-<br />
| [[DIP22]]<br />
| Private symbol visibility<br />
| Draft<br />
| Modification of private & Co symbol rules to reduce name clashes. Add internal linkage storage class.<br />
|<br />
|-<br />
| [[DIP23]]<br />
| Fixing property redux<br />
| Draft<br />
|Initial<br />
|-<br />
| [[DIP24]]<br />
| Fixing properties and optional parens.<br />
| Draft<br />
| Fixing properties and optional parens. Only those. In a general and straightforward way. (counter proposal to DIP23)<br />
|-<br />
| [[DIP25]]<br />
| Sealed references<br />
| Draft<br />
|-<br />
| [[DIP26]]<br />
| Properties the other way round<br />
| Draft<br />
|<br />
|-<br />
| [[DIP27]]<br />
| Function definition<br />
| Draft<br />
|<br />
|-<br />
| [[DIP28]]<br />
| Property definition<br />
| Draft<br />
|<br />
|-<br />
| [[DIP29]]<br />
| Unique pointers<br />
| Draft<br />
| Unique pointers can be implicitly cast to/from immutable and shared.<br />
|<br />
|-<br />
| [[DIP30]]<br />
| Delegate definition<br />
| Draft<br />
|<br />
|-<br />
| [[DIP31]]<br />
| Defined compile time paradox resolution<br />
| Draft<br />
|<br />
|-<br />
| [[DIP32]]<br />
| Uniform tuple syntax<br />
| Draft<br />
|<br />
|-<br />
| [[DIP33]]<br />
| A standard exception hierarchy<br />
| Draft<br />
|<br />
|-<br />
| [[DIP34]]<br />
| Static array literals<br />
| Draft<br />
|<br />
|-<br />
| [[DIP35]]<br />
| [[DIP25|Sealed References]] Amendment<br />
| Draft<br />
|<br />
|-<br />
| [[DIP36]]<br />
| Rvalue References<br />
| Rejected<br />
|<br />
|-<br />
| [[DIP37]]<br />
| Importing Packages as if They Were Modules<br />
| '''Implemented'''<br />
| Allow for packages to be imported as if they were modules by providing a ''package.d'' file.<br />
|<br />
|-<br />
| [[DIP38]]<br />
| Safe references without runtime checks<br />
| Draft<br />
|<br />
|-<br />
| [[DIP39]]<br />
| Safe rvalue references: backwards compatible, safe against ref/nonref code evolution, compatible with UFCS and DIP38.<br />
| Draft<br />
|<br />
|-<br />
| [[DIP40]]<br />
| Template parameter deduction for constructors.<br />
| Draft<br />
|<br />
|-<br />
| [[DIP41]]<br />
| dmd/rdmd command line overhaul.<br />
| Draft<br />
|<br />
|-<br />
| [[DIP42]]<br />
| Support enum E(T) = expression; for manifest constants<br />
| '''Implemented'''<br />
|<br />
|-<br />
| [[DIP43]]<br />
| D/Objective-C<br />
| Draft<br />
| Adds language extensions to make D ABI compatible with Objective-C.<br />
|-<br />
| [[DIP44]]<br />
| scope(this)<br />
| Draft<br />
| Extends scope guards to class / struct lifetime.<br />
|-<br />
| [[DIP45]]<br />
| making export an attribute<br />
| Draft<br />
| Turn export into an attribute and fix various shortcomings of its current implementation.<br />
|-<br />
| [[DIP46]]<br />
| region based storage allocation<br />
| Draft<br />
| Library addition to GC to allow for region based allocation strategies<br />
|}<br />
<br />
----<br />
[[Category:DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2933DIP452013-08-30T15:48:29Z<p>Ingrater: </p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''making export an attribute'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-08-30<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com<br />
http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Export and its behavior needs to be changed in serveral ways to make it work on Windows and allow better code generation for other plattforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
* The 'export' protection level should be turned into a 'export' attribute.<br />
* If a module contains a single symbol annotated with the 'export' attribute all compiler internal symbols of this module should recieve the 'export' attribute too (e.g. module info).<br />
* If a class is annotated with the 'export' attribute, all of its public and protected functions and members will automatically recieve the 'export' attribute. Also all its hidden compiler specific symbols will recieve the 'export' attribute.<br />
* It should be possible to access TLS variables which are stored in a DLL / shared library.<br />
<br />
==Rationale==<br />
<br />
Work in progress<br />
<br />
==Implementation Details==<br />
<br />
Work in progress<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2922DIP452013-08-27T10:06:35Z<p>Ingrater: /* Description */</p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''exoport(identifier)'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-08-27<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Add a identifier to the export protection level to make it useable for dll import/export on windows platforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
The 'export' protection level should be extended by a identifier so that<br />
<br />
export void libraryFunction();<br />
<br />
becomes<br />
<br />
export(exampleLib) void libraryFunction();<br />
<br />
Also two new command line parameters should be added to the compiler:<br />
<br />
*"-import identifier": which turns all export protected symbols with a matching identifier into dllimport<br />
*"-export identifier": which turns all export protected symbols with a matching identifier into dllexport<br />
<br />
If none of the above two compiler options is given for a export(identifier) protection it does not have any effect at all.<br />
<br />
For backwards compatibility export without a identifier will become export(default) implicitly. When transitioning to this new system no code needs to be changed. Only "-import default" and "-export default" needs to be added when compiling.<br />
<br />
On platforms not requiring dllimport/dllexport the command line parameters are not available and the export protection level does not have any effect.<br />
<br />
==Rationale==<br />
<br />
The 'export' protection level was originally designed to work as the equivalent of C++ __declspec(dllimport) and __declspec(dllexport) at the same time.<br />
This however does not work, as the compiler cannot know without giving it additional context which 'export' are dllimport, which are dllexport and which are to be ignored.<br />
<br />
Consider the following example:<br />
Two libraries A and B exists. Both of them are used by an executable. The library B uses library A.<br />
<br />
* While compiling library A as shared library all 'export' protected symbols inside the source of A need to be treated as dllexport.<br />
* While compiling library B as shared library all 'export' protected symbols inside the source of A need to be treated as dllimport. All 'export' protected symbols inside the source of B need to be treated as dllexport.<br />
* When compiling the executable all 'export' protected symbols inside the source of A and B need to be treated as dllimport.<br />
* When compiling library A or B as static library 'export' should not have any effect at all.<br />
<br />
<br />
Usign the identifier and command lines switches proposed in this DIP makes it possible to cover all of the above cases. Please also note that the exact same source code can be used to cover all the above cases. Using .di files is possible but not required to make it work.<br />
<br />
Using this DIP the above example implemented might look as follows<br />
<syntaxhighlight lang=D><br />
module libA;<br />
<br />
export(libA):<br />
<br />
__gshared int libAVar;<br />
int libAFunc()<br />
{<br />
return 5;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module libB:<br />
import libA;<br />
<br />
export(libB):<br />
<br />
int libBFunc()<br />
{<br />
return libAFunc() + libAVar;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module main;<br />
import libA;<br />
import libB;<br />
<br />
void main(string[] args)<br />
{<br />
printf("%d %d", libAFunc(), libBFunc());<br />
}<br />
</syntaxhighlight><br />
<br />
Compiling libA as shared library<br />
<br />
dmd -m64 -export libA -of"libA.dll" dllmain.d libA.d -L/DLL -L/IMPLIB:"libA.lib"<br />
<br />
Compiling libB as shared library<br />
<br />
dmd -m64 -export libB -import libA -of"libB.dll" dllmain.d libB.d -L/DLL -L/IMPLIB:"libB.lib" -LlibA.lib<br />
<br />
Compiling the executable<br />
<br />
dmd -m64 -import libB -import libA main.d -LlibA.lib -LlibB.lib<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2921DIP452013-08-27T10:04:37Z<p>Ingrater: /* Rationale */</p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''exoport(identifier)'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-08-27<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Add a identifier to the export protection level to make it useable for dll import/export on windows platforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
The 'export' protection level should be extended by a identifier so that<br />
<br />
export void libraryFunction();<br />
<br />
becomes<br />
<br />
export(exampleLib) void libraryFunction();<br />
<br />
Also two new command lines parameters should be added to the compiler:<br />
<br />
*"-import identifier": which turns all export protected symbols with a matching identifier into dllimport<br />
*"-export identifier": which turns all export protected symbols with a matching identifier into dllexport<br />
<br />
If none of the above two compiler options is given for a export(identifier) protection it does not have any effect at all.<br />
<br />
For backwards compatibility export without a identifier will become export(default) implicitly. When transitioning to this new system no code needs to be changed. Only "-import default" and "-export default" needs to be added when compiling.<br />
<br />
On platforms not requiring dllimport/dllexport the command line parameters are not available and the export protection level does not have any effect.<br />
<br />
==Rationale==<br />
<br />
The 'export' protection level was originally designed to work as the equivalent of C++ __declspec(dllimport) and __declspec(dllexport) at the same time.<br />
This however does not work, as the compiler cannot know without giving it additional context which 'export' are dllimport, which are dllexport and which are to be ignored.<br />
<br />
Consider the following example:<br />
Two libraries A and B exists. Both of them are used by an executable. The library B uses library A.<br />
<br />
* While compiling library A as shared library all 'export' protected symbols inside the source of A need to be treated as dllexport.<br />
* While compiling library B as shared library all 'export' protected symbols inside the source of A need to be treated as dllimport. All 'export' protected symbols inside the source of B need to be treated as dllexport.<br />
* When compiling the executable all 'export' protected symbols inside the source of A and B need to be treated as dllimport.<br />
* When compiling library A or B as static library 'export' should not have any effect at all.<br />
<br />
<br />
Usign the identifier and command lines switches proposed in this DIP makes it possible to cover all of the above cases. Please also note that the exact same source code can be used to cover all the above cases. Using .di files is possible but not required to make it work.<br />
<br />
Using this DIP the above example implemented might look as follows<br />
<syntaxhighlight lang=D><br />
module libA;<br />
<br />
export(libA):<br />
<br />
__gshared int libAVar;<br />
int libAFunc()<br />
{<br />
return 5;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module libB:<br />
import libA;<br />
<br />
export(libB):<br />
<br />
int libBFunc()<br />
{<br />
return libAFunc() + libAVar;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<syntaxhighlight lang=D><br />
module main;<br />
import libA;<br />
import libB;<br />
<br />
void main(string[] args)<br />
{<br />
printf("%d %d", libAFunc(), libBFunc());<br />
}<br />
</syntaxhighlight><br />
<br />
Compiling libA as shared library<br />
<br />
dmd -m64 -export libA -of"libA.dll" dllmain.d libA.d -L/DLL -L/IMPLIB:"libA.lib"<br />
<br />
Compiling libB as shared library<br />
<br />
dmd -m64 -export libB -import libA -of"libB.dll" dllmain.d libB.d -L/DLL -L/IMPLIB:"libB.lib" -LlibA.lib<br />
<br />
Compiling the executable<br />
<br />
dmd -m64 -import libB -import libA main.d -LlibA.lib -LlibB.lib<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2920DIP452013-08-27T09:51:22Z<p>Ingrater: /* Description */</p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''exoport(identifier)'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-08-27<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Add a identifier to the export protection level to make it useable for dll import/export on windows platforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
The 'export' protection level should be extended by a identifier so that<br />
<br />
export void libraryFunction();<br />
<br />
becomes<br />
<br />
export(exampleLib) void libraryFunction();<br />
<br />
Also two new command lines parameters should be added to the compiler:<br />
<br />
*"-import identifier": which turns all export protected symbols with a matching identifier into dllimport<br />
*"-export identifier": which turns all export protected symbols with a matching identifier into dllexport<br />
<br />
If none of the above two compiler options is given for a export(identifier) protection it does not have any effect at all.<br />
<br />
For backwards compatibility export without a identifier will become export(default) implicitly. When transitioning to this new system no code needs to be changed. Only "-import default" and "-export default" needs to be added when compiling.<br />
<br />
On platforms not requiring dllimport/dllexport the command line parameters are not available and the export protection level does not have any effect.<br />
<br />
==Rationale==<br />
<br />
The 'export' protection level was originally designed to work as the equivalent of C++ __declspec(dllimport) and __declspec(dllexport) at the same time.<br />
This however does not work, as the compiler cannot know without giving it additional context which 'export' are dllimport, which are dllexport and which are to be ignored.<br />
<br />
Consider the following example:<br />
Two libraries A and B exists. Both of them are used by an executable. The library B uses library A.<br />
<br />
* While compiling library A as shared library all 'export' protected symbols inside the source of A need to be treated as dllexport.<br />
* While compiling library B as shared library all 'export' protected symbols inside the source of A need to be treated as dllimport. All 'export' protected symbols inside the source of B need to be treated as dllexport.<br />
* When compiling the executable all 'export' protected symbols inside the source of A and B need to be treated as dllimport.<br />
* When compiling library A or B as static library 'export' should not have any effect at all.<br />
<br />
<br />
Usign the identifier and command lines switches proposed in this DIP makes it possible to cover all of the above cases.<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2919DIP452013-08-27T08:09:36Z<p>Ingrater: /* Rationale */</p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''exoport(identifier)'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-08-27<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Add a identifier to the export protection level to make it useable for dll import/export on windows platforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
Work in progress.<br />
<br />
<br />
==Rationale==<br />
<br />
The 'export' protection level was originally designed to work as the equivalent of C++ __declspec(dllimport) and __declspec(dllexport) at the same time.<br />
This however does not work, as the compiler cannot know without giving it additional context which 'export' are dllimport, which are dllexport and which are to be ignored.<br />
<br />
Consider the following example:<br />
Two libraries A and B exists. Both of them are used by an executable. The library B uses library A.<br />
<br />
* While compiling library A as shared library all 'export' protected symbols inside the source of A need to be treated as dllexport.<br />
* While compiling library B as shared library all 'export' protected symbols inside the source of A need to be treated as dllimport. All 'export' protected symbols inside the source of B need to be treated as dllexport.<br />
* When compiling the executable all 'export' protected symbols inside the source of A and B need to be treated as dllimport.<br />
* When compiling library A or B as static library 'export' should not have any effect at all.<br />
<br />
<br />
Usign the identifier and command lines switches proposed in this DIP makes it possible to cover all of the above cases.<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIP45&diff=2918DIP452013-08-27T08:08:03Z<p>Ingrater: Created page with "{| class="wikitable" !Title: !'''exoport(identifier)''' |- |DIP: |45 |- |Version: |1 |- |Status: |Draft |- |Created: |2013-08-27 |- |Last Modified: |2013-08-27 |- |Author: |Be..."</p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''exoport(identifier)'''<br />
|-<br />
|DIP:<br />
|45<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-08-27<br />
|-<br />
|Last Modified:<br />
|2013-08-27<br />
|-<br />
|Author:<br />
|Benjamin Thaut<br />
|-<br />
|Links:<br />
|http://forum.dlang.org/post/5112D61B.5010905@digitalmars.com<br />
http://d.puremagic.com/issues/show_bug.cgi?id=9816<br />
|}<br />
<br />
==Abstract==<br />
<br />
Add a identifier to the export protection level to make it useable for dll import/export on windows platforms. The Rationale section explains the problem and shows how this DIP solves it.<br />
<br />
==Description==<br />
<br />
Work in progress.<br />
<br />
<br />
==Rationale==<br />
<br />
The 'export' protection level was originally designed to work as the equivalent of C++ __declspec(dllimport) and __declspec(dllexport) at the same time.<br />
This however does not work, as the compiler cannot know without giving it additional context which 'export' are dllimport, which are dllexport and which are to be ignored.<br />
<br />
Consider the following example:<br />
Two libraries A and B exists. Both of them are used by an executable. The library B uses library A.<br />
<br />
- While compiling library A as shared library all 'export' protected symbols inside the source of A need to be treated as dllexport.<br />
- While compiling library B as shared library all 'export' protected symbols inside the source of A need to be treated as dllimport. All 'export' protected symbols inside the source of B need to be treated as dllexport.<br />
- When compiling the executable all 'export' protected symbols inside the source of A and B need to be treated as dllimport.<br />
- When compiling library A or B as static library 'export' should not have any effect at all.<br />
<br />
<br />
Usign the identifier and command lines switches proposed in this DIP makes it possible to cover all of the above cases. <br />
<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>Ingraterhttps://wiki.dlang.org/?title=DIPs&diff=2917DIPs2013-08-27T07:43:48Z<p>Ingrater: </p>
<hr />
<div>{| class="wikitable sortable"<br />
! ID<br />
! Title<br />
! Status<br />
! Description<br />
|-<br />
| [[DIP1]]<br />
| Template DIP<br />
| Draft<br />
| This is a DIP template that can be used as a model to start a new proposal.<br />
|-<br />
| [[DIP2]]<br />
| Const code bloat<br />
| '''Approved'''<br />
| proposed solution for [http://d.puremagic.com/issues/show_bug.cgi?id=1961 bug 1961].<br />
|-<br />
| [[DIP3]]<br />
| Remove inheritance protection<br />
| '''Approved'''<br />
| non-public inheritance in a single inheritance language that has a single root object hierarchy makes little sense.<br />
|-<br />
| [[DIP4]]<br />
| Properties<br />
| [[DIP6|Superseded by DIP6]]<br />
| an alternate usage/definition syntax for properties.<br />
|-<br />
| [[DIP5]]<br />
| Properties 2<br />
| [[DIP6|Superseded by DIP6]]<br />
| a variant of DIP4.<br />
|-<br />
| [[DIP6]]<br />
| Annotations<br />
| '''Approved'''<br />
| extend the D programming language with annotations.<br />
|-<br />
| [[DIP7]]<br />
| Operator overloading<br />
| '''Approved'''<br />
| Revamped operator overloading.<br />
|-<br />
| [[DIP8]]<br />
| Improving Runtime Type Info<br />
| Draft<br />
| Templating RTTI.<br />
|-<br />
| [[DIP9]]<br />
| Redo toString API<br />
| Draft<br />
| Replace inefficient aggregate toString API with efficient delegate-based version that supports formatting.<br />
|-<br />
| [[DIP10]]<br />
| Qualified constructors and destructors for structs<br />
| Draft<br />
|<br />
|-<br />
| [[DIP11]]<br />
| Automatic downloading of imports<br />
| Draft<br />
| Support automatically downloading imported files via new import path specifications or pragmas.<br />
|-<br />
| [[DIP12]]<br />
| C API Headers<br />
| '''Approved'''<br />
| Collection of D headers for common C libraries.<br />
|-<br />
| [[DIP13]]<br />
| Import path binding<br />
| Draft<br />
| Allow to bind an import path to a package.<br />
|-<br />
| [[DIP14]]<br />
| Import path binding in source code<br />
| Draft<br />
| Allow to bind an import path to a package from within sources.<br />
|-<br />
| [[DIP15]]<br />
| Import of packages<br />
| [[DIP37|Superseded by DIP37]]<br />
| Improve imports of packages with submodules.<br />
|-<br />
| [[DIP16]]<br />
| Transparently substitute module with package<br />
| [[DIP37|Superseded by DIP37]]<br />
|<br />
|-<br />
| [[DIP17]]<br />
| Sane volatile statement<br />
| [[DIP20|Superseded by DIP20]]<br />
|<br />
|-<br />
| [[DIP18]]<br />
| Non-GC Threads<br />
| Draft<br />
|<br />
|-<br />
| [[DIP20]]<br />
| Volatile read/write intrinsics<br />
| Draft<br />
| Intrinsics to perform C-style volatile loads/stores from/to memory.<br />
|-<br />
| [[DIP21]]<br />
| Fixing property<br />
| Draft<br />
|<br />
|-<br />
| [[DIP22]]<br />
| Private symbol visibility<br />
| Draft<br />
| Modification of private & Co symbol rules to reduce name clashes. Add internal linkage storage class.<br />
|<br />
|-<br />
| [[DIP23]]<br />
| Fixing property redux<br />
| Draft<br />
|Initial<br />
|-<br />
| [[DIP24]]<br />
| Fixing properties and optional parens.<br />
| Draft<br />
| Fixing properties and optional parens. Only those. In a general and straightforward way. (counter proposal to DIP23)<br />
|-<br />
| [[DIP25]]<br />
| Sealed references<br />
| Draft<br />
|-<br />
| [[DIP26]]<br />
| Properties the other way round<br />
| Draft<br />
|<br />
|-<br />
| [[DIP27]]<br />
| Function definition<br />
| Draft<br />
|<br />
|-<br />
| [[DIP28]]<br />
| Property definition<br />
| Draft<br />
|<br />
|-<br />
| [[DIP29]]<br />
| Unique pointers<br />
| Draft<br />
| Unique pointers can be implicitly cast to/from immutable and shared.<br />
|<br />
|-<br />
| [[DIP30]]<br />
| Delegate definition<br />
| Draft<br />
|<br />
|-<br />
| [[DIP31]]<br />
| Defined compile time paradox resolution<br />
| Draft<br />
|<br />
|-<br />
| [[DIP32]]<br />
| Uniform tuple syntax<br />
| Draft<br />
|<br />
|-<br />
| [[DIP33]]<br />
| A standard exception hierarchy<br />
| Draft<br />
|<br />
|-<br />
| [[DIP34]]<br />
| Static array literals<br />
| Draft<br />
|<br />
|-<br />
| [[DIP35]]<br />
| [[DIP25|Sealed References]] Amendment<br />
| Draft<br />
|<br />
|-<br />
| [[DIP36]]<br />
| Rvalue References<br />
| Rejected<br />
|<br />
|-<br />
| [[DIP37]]<br />
| Importing Packages as if They Were Modules<br />
| '''Implemented'''<br />
| Allow for packages to be imported as if they were modules by providing a ''package.d'' file.<br />
|<br />
|-<br />
| [[DIP38]]<br />
| Safe references without runtime checks<br />
| Draft<br />
|<br />
|-<br />
| [[DIP39]]<br />
| Safe rvalue references: backwards compatible, safe against ref/nonref code evolution, compatible with UFCS and DIP38.<br />
| Draft<br />
|<br />
|-<br />
| [[DIP40]]<br />
| Template parameter deduction for constructors.<br />
| Draft<br />
|<br />
|-<br />
| [[DIP41]]<br />
| dmd/rdmd command line overhaul.<br />
| Draft<br />
|<br />
|-<br />
| [[DIP42]]<br />
| Support enum E(T) = expression; for manifest constants<br />
| '''Implemented'''<br />
|<br />
|-<br />
| [[DIP43]]<br />
| D/Objective-C<br />
| Draft<br />
| Adds language extensions to make D ABI compatible with Objective-C.<br />
|-<br />
| [[DIP44]]<br />
| scope(this)<br />
| Draft<br />
| Extends scope guards to class / struct lifetime.<br />
|-<br />
| [[DIP45]]<br />
| export(identifier)<br />
| Draft<br />
| Adds a identifier to the export protection level to make it usable for dll import/export on windows.<br />
|}<br />
<br />
----<br />
[[Category:DIP]]</div>Ingrater