www.digitalmars.com         C & C++   DMDScript  

D.gnu - How minimal I can go using D on GDC?

reply "Rel" <relmail rambler.ru> writes:
hello! I used to have a bit unusual task: writing pure binary 
code (without runtime/os dependency, just native x86 and x64 
code). Quite similar to the OS kernel development I may say, if 
it makes the problem clearer for you. I usually wrote such code 
in C++ with GCC (using '-nostdlib', '-fno-exceptions', 
'-fno-rtti' and etc), but now I need a good metaprogramming 
features and complex metaprogramming in C++ makes a brain 
explode. D metaprogramming and the language in general looks 
awesome, so I decided to give it a try.

I looked at the XOMB and a few other projects, but it seems they 
reimplemented quite big part of druntime to make their project 
work, in fact a lot of stuff reimplemented by them I would 
consider being actually useless. So my question is: how much of 
the runtime features I could disable?

for testing purposes I made a little programm (I'm building it 
with '-nophoboslib', '-nostdlib', '-fno-exceptions', '-emain'):

module main;

extern (C) void* _Dmodule_ref = null;
extern (C) void puts(const char*);
extern (C) void exit(int);

extern (C) void main() {
	scope(exit) {
		puts("Exiting!");
		exit(0);
	}
	
	puts("Hello World!");
}

I had to include '_Dmodule_ref' in the source, it seems that it 
is used for calling module constructors, I'm not going to use 
them, can I disable it somehow?

when I added 'scope(exit)' part I got links to exception handling 
code in object files, I'm not going to use exceptions, so I added 
'-fno-exceptions' flag, and it seems to work pretty fine. but 
when I try to add some primitive classese I got a lot of links to 
the code that seems to be connected with runtime type 
information, I don't need it so I tried to add '-fno-rtti' flag, 
but it doesn't work. Is there a way to get rid of runtime type 
information?
May 11 2013
next sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 11.05.2013 17:51, schrieb Rel:
 hello! I used to have a bit unusual task: writing pure binary code
 (without runtime/os dependency, just native x86 and x64 code). Quite
 similar to the OS kernel development I may say, if it makes the problem
 clearer for you. I usually wrote such code in C++ with GCC (using
 '-nostdlib', '-fno-exceptions', '-fno-rtti' and etc), but now I need a
 good metaprogramming features and complex metaprogramming in C++ makes a
 brain explode. D metaprogramming and the language in general looks
 awesome, so I decided to give it a try.

 I looked at the XOMB and a few other projects, but it seems they
 reimplemented quite big part of druntime to make their project work, in
 fact a lot of stuff reimplemented by them I would consider being
 actually useless. So my question is: how much of the runtime features I
 could disable?

 for testing purposes I made a little programm (I'm building it with
 '-nophoboslib', '-nostdlib', '-fno-exceptions', '-emain'):

 module main;

 extern (C) void* _Dmodule_ref = null;
 extern (C) void puts(const char*);
 extern (C) void exit(int);

 extern (C) void main() {
      scope(exit) {
          puts("Exiting!");
          exit(0);
      }

      puts("Hello World!");
 }

 I had to include '_Dmodule_ref' in the source, it seems that it is used
 for calling module constructors, I'm not going to use them, can I
 disable it somehow?

 when I added 'scope(exit)' part I got links to exception handling code
 in object files, I'm not going to use exceptions, so I added
 '-fno-exceptions' flag, and it seems to work pretty fine. but when I try
 to add some primitive classese I got a lot of links to the code that
 seems to be connected with runtime type information, I don't need it so
 I tried to add '-fno-rtti' flag, but it doesn't work. Is there a way to
 get rid of runtime type information?
GDC has -nodefaultlib flag which will disable linking against the standard library. This is as bare metal as it gets, just start writing all functions you will get linker errors for. Be warned a lot of language features will break that way, eg: - Everything that relies on the GC (closures, array literals, etc) - Module Constructors / Destructors - Thread local storage I've also seen that there is a minmal druntime somewhere on the web, but I can't find it right now. Kind Regards Benjamin Thaut
May 12 2013
parent reply "Rel" <relmail rambler.ru> writes:
Benjamin Thaut, yes I know. but here is an example, if I add a 
class to the code like that:

module main;

extern (C) void* _Dmodule_ref = null;
extern (C) void printf(const char*, ...);
extern (C) void puts(const char*);
extern (C) void exit(int);

class A {
	int a = 100;
	int b = 200;
};

extern (C) void main() {
	scope(exit) {
		puts("Exiting!");
		exit(0);
	}

	A a; printf("%d %d\n", a.a, a.b);
}

I would get a lot of undefined symbols like 
'_D14TypeInfo_Class6__vtblZ', '_D6object6Object8toStringMFZAya', 
'_D6object6Object6toHashMFZk' and etc. I don't really need any 
runtime type information, is there a way to make a compiler not 
generating typeinfos ('-fno-rtti' doesn't work)?
May 12 2013
next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 12 May 2013 15:41, Rel <relmail rambler.ru> wrote:

 Benjamin Thaut, yes I know. but here is an example, if I add a class to
 the code like that:


 module main;

 extern (C) void* _Dmodule_ref = null;
 extern (C) void printf(const char*, ...);

 extern (C) void puts(const char*);
 extern (C) void exit(int);

 class A {
         int a = 100;
         int b = 200;

 };

 extern (C) void main() {
         scope(exit) {
                 puts("Exiting!");
                 exit(0);
         }

         A a; printf("%d %d\n", a.a, a.b);
 }

 I would get a lot of undefined symbols like '_D14TypeInfo_Class6__vtblZ',
 '_**D6object6Object8toStringMFZAya**', '_D6object6Object6toHashMFZk' and
 etc. I don't really need any runtime type information, is there a way to
 make a compiler not generating typeinfos ('-fno-rtti' doesn't work)?
If you want to use classes, there must *always* be an Object class defined somewhere to link to. All classes derive from Object. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
May 12 2013
prev sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 12 May 2013 15:41, Rel <relmail rambler.ru> wrote:

 Benjamin Thaut, yes I know. but here is an example, if I add a class to
 the code like that:


 module main;

 extern (C) void* _Dmodule_ref = null;
 extern (C) void printf(const char*, ...);

 extern (C) void puts(const char*);
 extern (C) void exit(int);

 class A {
         int a = 100;
         int b = 200;

 };

 extern (C) void main() {
         scope(exit) {
                 puts("Exiting!");
                 exit(0);
         }

         A a; printf("%d %d\n", a.a, a.b);
 }
This code won't work. classes are reference types and need to be initialised with 'new'. This requires TypeInfo_Class information to do... You could possible use 'scope A a = new A'. But again your going into the bounds of needing rtti for the initialiser var to assign it on the stack. Structs would be your friend here... -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
May 12 2013
parent reply "Timo Sintonen" <t.sintonen luukku.com> writes:
On Sunday, 12 May 2013 at 15:27:04 UTC, Iain Buclaw wrote:
 On 12 May 2013 15:41, Rel <relmail rambler.ru> wrote:

 Benjamin Thaut, yes I know. but here is an example, if I add a 
 class to
 the code like that:


 module main;

 extern (C) void* _Dmodule_ref = null;
 extern (C) void printf(const char*, ...);

 extern (C) void puts(const char*);
 extern (C) void exit(int);

 class A {
         int a = 100;
         int b = 200;

 };

 extern (C) void main() {
         scope(exit) {
                 puts("Exiting!");
                 exit(0);
         }

         A a; printf("%d %d\n", a.a, a.b);
 }
This code won't work. classes are reference types and need to be initialised with 'new'. This requires TypeInfo_Class information to do... You could possible use 'scope A a = new A'. But again your going into the bounds of needing rtti for the initialiser var to assign it on the stack. Structs would be your friend here...
I have used the option -fno-emit-moduleinfo and got rid of _Dmodule_ref Anything created with 'new' needs memory allocation. I have just published a minimum memory allocation in my repo. The address of my minimum runtime environment repository is: bitbucket.org/timosi/minlibd
May 12 2013
next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 12 May 2013 18:13, Timo Sintonen <t.sintonen luukku.com> wrote:

 On Sunday, 12 May 2013 at 15:27:04 UTC, Iain Buclaw wrote:

 On 12 May 2013 15:41, Rel <relmail rambler.ru> wrote:

  Benjamin Thaut, yes I know. but here is an example, if I add a class to
 the code like that:


 module main;

 extern (C) void* _Dmodule_ref = null;
 extern (C) void printf(const char*, ...);

 extern (C) void puts(const char*);
 extern (C) void exit(int);

 class A {
         int a = 100;
         int b = 200;

 };

 extern (C) void main() {
         scope(exit) {
                 puts("Exiting!");
                 exit(0);
         }

         A a; printf("%d %d\n", a.a, a.b);
 }
This code won't work. classes are reference types and need to be initialised with 'new'. This requires TypeInfo_Class information to do... You could possible use 'scope A a = new A'. But again your going into the bounds of needing rtti for the initialiser var to assign it on the stack. Structs would be your friend here...
I have used the option -fno-emit-moduleinfo and got rid of _Dmodule_ref
I completely forgot that I put that in. Well done me *pats own back*. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
May 12 2013
prev sibling next sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
Last time I tried such stuff there was a TypeInfo emitted for 
templated structs. Is this still the case?
May 13 2013
parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 13 May 2013 09:11, Dicebot <m.strashun gmail.com> wrote:

 Last time I tried such stuff there was a TypeInfo emitted for templated
 structs. Is this still the case?
Why would you use templates in low level (eg: kernel) code? -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
May 13 2013
parent "Dicebot" <m.strashun gmail.com> writes:
On Monday, 13 May 2013 at 08:24:52 UTC, Iain Buclaw wrote:
 On 13 May 2013 09:11, Dicebot <m.strashun gmail.com> wrote:

 Last time I tried such stuff there was a TypeInfo emitted for 
 templated
 structs. Is this still the case?
Why would you use templates in low level (eg: kernel) code?
Why would I chose D over C if I am restricted from templates? Templates are essentially an automated type-safe copy-paste and there is a lot of copy-paste in type kernel-flavor code to be eliminated. Or, to be more specific, why shouldn't I? As you may notice, this topic author uses C++ meta-programming just fine in this environment, no reason D can't do it. (feels like all my previous rants on this topic got unnoticed =/)
May 13 2013
prev sibling parent reply "Mr. Anonymous" <mailnew4ster gmail.com> writes:
On Sunday, 12 May 2013 at 17:13:30 UTC, Timo Sintonen wrote:
 On Sunday, 12 May 2013 at 15:27:04 UTC, Iain Buclaw wrote:
 On 12 May 2013 15:41, Rel <relmail rambler.ru> wrote:

 Benjamin Thaut, yes I know. but here is an example, if I add 
 a class to
 the code like that:


 module main;

 extern (C) void* _Dmodule_ref = null;
 extern (C) void printf(const char*, ...);

 extern (C) void puts(const char*);
 extern (C) void exit(int);

 class A {
        int a = 100;
        int b = 200;

 };

 extern (C) void main() {
        scope(exit) {
                puts("Exiting!");
                exit(0);
        }

        A a; printf("%d %d\n", a.a, a.b);
 }
This code won't work. classes are reference types and need to be initialised with 'new'. This requires TypeInfo_Class information to do... You could possible use 'scope A a = new A'. But again your going into the bounds of needing rtti for the initialiser var to assign it on the stack. Structs would be your friend here...
I have used the option -fno-emit-moduleinfo and got rid of _Dmodule_ref Anything created with 'new' needs memory allocation. I have just published a minimum memory allocation in my repo. The address of my minimum runtime environment repository is: bitbucket.org/timosi/minlibd
Will this minimum runtime environment work on Windows, too? I'd like to try that out.
May 13 2013
parent reply "Timo Sintonen" <t.sintonen luukku.com> writes:
On Monday, 13 May 2013 at 20:21:55 UTC, Mr. Anonymous wrote:
 Will this minimum runtime environment work on Windows, too?
 I'd like to try that out.
I see no reason why this would not work. The only thing that is needed is a working cross compiler. I have not heard of gdc cross compilers for windows and I do not have time and interest to play with that. This question has been asked several times so I think there is interest for this. If someone wants to try, there are several options: - The compiler can made step by step. The instructions are here: http://gdcproject.org/wiki/Cross%20Compiler - Use the native windows version and make it a cross compiler. I would like to hear a comment from mingw people if this is possible. - There are full cross tools chains that use gcc like this: https://launchpad.net/gcc-arm-embedded Gdc could be added to gcc there. As long as gdc is not part of gcc, there will not be any ready-to-use D toolchain. If there is any success, I would like to hear it .
May 13 2013
parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 14 May 2013 06:14, Timo Sintonen <t.sintonen luukku.com> wrote:

 On Monday, 13 May 2013 at 20:21:55 UTC, Mr. Anonymous wrote:

 Will this minimum runtime environment work on Windows, too?
 I'd like to try that out.
I see no reason why this would not work. The only thing that is needed is a working cross compiler.
Indeed, if it's a free-standing runtime environment. Then it could be moved and put anywhere.
 As long as gdc is not part of gcc, there will not be any ready-to-use D
 toolchain. If there is any success, I would like to hear it
 .
This logic is backwards. Go is part of gcc but there is still no ready-to-use toolchain available for, say, PPC or IA64. We don't need to be part of gcc to get toolchains up for platforms. Just need the people willing enough to port and support them. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
May 14 2013
prev sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 11 May 2013 16:51, Rel <relmail rambler.ru> wrote:

 hello! I used to have a bit unusual task: writing pure binary code
 (without runtime/os dependency, just native x86 and x64 code). Quite
 similar to the OS kernel development I may say, if it makes the problem
 clearer for you. I usually wrote such code in C++ with GCC (using
 '-nostdlib', '-fno-exceptions', '-fno-rtti' and etc), but now I need a good
 metaprogramming features and complex metaprogramming in C++ makes a brain
 explode. D metaprogramming and the language in general looks awesome, so I
 decided to give it a try.

 I looked at the XOMB and a few other projects, but it seems they
 reimplemented quite big part of druntime to make their project work, in
 fact a lot of stuff reimplemented by them I would consider being actually
 useless. So my question is: how much of the runtime features I could
 disable?

 for testing purposes I made a little programm (I'm building it with
 '-nophoboslib', '-nostdlib', '-fno-exceptions', '-emain'):

 module main;

 extern (C) void* _Dmodule_ref = null;
 extern (C) void puts(const char*);
 extern (C) void exit(int);

 extern (C) void main() {
         scope(exit) {
                 puts("Exiting!");
                 exit(0);
         }

         puts("Hello World!");
 }

 I had to include '_Dmodule_ref' in the source, it seems that it is used
 for calling module constructors, I'm not going to use them, can I disable
 it somehow?

 when I added 'scope(exit)' part I got links to exception handling code in
 object files, I'm not going to use exceptions, so I added '-fno-exceptions'
 flag, and it seems to work pretty fine. but when I try to add some
 primitive classese I got a lot of links to the code that seems to be
 connected with runtime type information, I don't need it so I tried to add
 '-fno-rtti' flag, but it doesn't work. Is there a way to get rid of runtime
 type information?
-nophoboslib tells the driver not to link to phobos/druntime. -nostdlib tells the driver not to link to any C libs. -fno-exceptions only puts in an error if it encounters a 'throw' statement. Doesn't actually prevent the front-end from generating throw/try/catch statements on the fly, or do anything that causes an exception to be raised, and I don't think it errors about the use of assert contracts either. Looking at the above, you use scope() statements. This really is just a nice way of expressing try { } catch { } finally { } without all the nested blocks. -fno-rtti is not adhered to, infact I didn't realise that it was even a common compiler switch (thought it was only in g++). This could be added in, not should on how good an idea it would be though... :) _Dmodule_ref should be possible to not define this via a compiler flag, but that has not yet been implemented. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
May 12 2013