Page 3 of 6

Re: OS in D language

Posted: Thu Jan 29, 2009 8:22 am
by Zenith
I looked into it, and found that "gcc-gdc" is just an old gcc built with an old gdc and distributed as binaries. It's still not officially supported by GCC, and the version available from cygwin is one from 2004... [Linky] :(

Re: OS in D language

Posted: Thu Jan 29, 2009 8:37 am
by quanganht
Zenith wrote:I looked into it, and found that "gcc-gdc" is just an old gcc built with an old gdc and distributed as binaries. It's still not officially supported by GCC, and the version available from cygwin is one from 2004... [Linky] :(
Oh, that's bad !

Re: OS in D language

Posted: Fri Jan 30, 2009 12:20 am
by AndrewAPrice
The latest version of GCC that GDC supports is 4.1.x so I've downloaded the latest source, now I'm building my own cross compiler from the sources of binutils, GCC, and GDC under Cygwin.

EDIT:
I'm compiling a GCC cross compiler (targeting i586-elf) with GDC patched in.
It's crashing on gcc/d/d-lang.cc saying D_OS_VERSYM is unidentified. I trace it down, and I see that D_OS_VERSYM is being declared in:
gcc/d/target-ver-syms.h:

Code: Select all

target=$1
target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`

d_target_os=`echo $target_os | sed 's/^\([A-Za-z_]+\)/\1/'`
case "$d_target_os" in
aix*) d_os_versym=aix ; d_unix=1 ;; 
coff*) ;;
cygwin*) d_os_versym=cygwin ; d_unix=1 ;;
darwin*) d_os_versym=darwin ; d_unix=1 ;;
elf*) ;;
freebsd*) d_os_versym=freebsd ; d_unix=1 ;;
linux*) d_os_versym=linux ; d_unix=1 ;; 
mingw32*) d_os_versym=Win32; d_windows=1 ;;
pe*)    case "$target" in
	    *-skyos*-*) d_os_versym=skyos ; d_unix=1 ;;
	esac
	;;
skyos*) d_os_versym=skyos ; d_unix=1 ;; # Doesn't actually work because SkyOS uses i386-skyos-pe
solaris*) d_os_versym=solaris; d_unix=1 ;;
sysv3*) d_os_versym=sysv3; d_unix=1 ;;
sysv4*) d_os_versym=sysv4; d_unix=1 ;;

*bsd*) d_os_versym=bsd ; d_unix=1 ;;

*) d_os_versym="$d_target_os"
esac

case "$target_cpu" in
alpha*)  d_cpu_versym=Alpha ; d_cpu_versym64=Alpha64 ;;
arm*)    d_cpu_versym=ARM ;;
i*86)    d_cpu_versym=X86   ; d_cpu_versym64=X86_64 ;;
mips*)   d_cpu_versym=MIPS  ; d_cpu_versym64=MIPS64 ;;
*ppc*)   d_cpu_versym=PPC   ; d_cpu_versym64=PPC64 ;;
powerpc*)d_cpu_versym=PPC   ; d_cpu_versym64=PPC64 ;;
sparc*)  d_cpu_versym=SPARC ; d_cpu_versym64=SPARC64 ;;
x86_64)  d_cpu_versym=X86   ; d_cpu_versym64=X86_64 ;;
esac

if test -n "$d_cpu_versym"; then
    echo "#define D_CPU_VERSYM \"$d_cpu_versym\""
fi
if test -n "$d_cpu_versym64"; then
    echo "#define D_CPU_VERSYM64 \"$d_cpu_versym64\""
fi
if test -n "$d_os_versym"; then
    echo "#define D_OS_VERSYM \"$d_os_versym\""
fi
Ummm.. "elf*) ;;" ? Setting this string to NULL causes compile errors ([url="http://forums.pittgeeks.org/viewtopic.php?f=38&t=702&p=4534"]ref[/url]). Though it says target, I'll using values like Win32, Cygwin, etc and see what works.

EDIT 2: Now I'm getting "kernel.kmain.d:0: error: code model 'kernel' not supported in the 32 bit mode" :(

Re: OS in D language

Posted: Fri Jan 30, 2009 8:02 am
by AndrewAPrice
I finally have the compiler set up and working. I'm trying to write a barebones D kernel.

Everything is linking correctly, however I'm doing this as follows:

I wrote an assembly stub that defined the multiboot header and jumped into _main then hangs.

Here is my kernel.main.d:

Code: Select all

module kernel.main;

extern(C) void main(uint magic, uint addr)
{
	byte *videoram = cast(byte *)0xb8000;
	videoram[0] = 65;
	videoram[1] = 0x07;
}
and here is my linker script:

Code: Select all

OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
SECTIONS
{
    /* 3GB+1MB virtual / 1MB physical */
    . = 0xC0100000;

    .text : AT(ADDR(.text) - 0xC0000000)
     {
        code = .; _code = .; __code = .;
        *(.text)
        *(.rodata*)
        /*. = ALIGN(4096);*/
    }

    .data ALIGN (0x1000) : AT(ADDR(.data) - 0xC0000000)
    {
        data = .; _data = .; __data = .;
        *(.data)
        /*. = ALIGN(4096);*/

        __CTOR_LIST__ = .; LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) *(.ctors)   LONG(0) __CTOR_END__ = .;
        __DTOR_LIST__ = .; LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) *(.dtors) LONG(0) __DTOR_END__ = .;
    }

    .bss : AT(ADDR(.bss) - 0xC0000000)
    {
        _sbss = .;
        bss = .; _bss = .; __bss = .;
        *(COMMON)
        *(.bss)
        _ebss = .;
        /*. = ALIGN(4096);*/
    }

    end = .; _end = .; __end = .;
}
It links fine, but the kernel then triple faults. Apparently it might be a linker issue since a lot of this thread warns that linker issues are the biggest barrier to using D?

I also suspect it may be a runtime issue because of
"byte *videoram = cast(byte *)0xb8000;"
The D programming specification states that "cast" is the equivalent of a dynamic_cast in C++, so then how do I do a static typecast?

I would really appreciate some help on exactly the runtime environment that is needed from others who have used D.

Re: OS in D language

Posted: Fri Jan 30, 2009 3:58 pm
by Wilkie
quanganht wrote:Testing now. I guess gdc will be include in gcc source code soon ~> cross-compiler no longer be the problem !
Well, you need cross compilation to support compiling without default binutils, etc.
MessiahAndrw wrote:Setting this string to NULL causes compile errors (ref)
Hey! That was us. You can set it to anything you like. It is "XOmB" or "PGOS" or something for us.
MessiahAndrw wrote:I also suspect it may be a runtime issue because of
"byte *videoram = cast(byte *)0xb8000;"
That should work fine. What is it doing when it returns from main? Because, well, that is always fun. I assume that the video memory is mapped correctly in your assembly.

Maybe I will extract a barebones from our code base. It will be 64-bit though.

Re: OS in D language

Posted: Fri Jan 30, 2009 9:31 pm
by AndrewAPrice
Wilkie wrote:Maybe I will extract a barebones from our code base. It will be 64-bit though.
That is a brilliant idea!

When it returns from main my assembler stub calls hlt. No interrupts are enabled,

Now GDC is complaining it needs object.d ?!

It would be good if you could explain exactly what sort of runtime is required and for what.

Thanks!

Re: OS in D language

Posted: Fri Jan 30, 2009 11:44 pm
by Wilkie
MessiahAndrw and any others:

First:
You will need a gdc built against nothing that targets your architecture (build a cross compiler). You will need gcc 4.1.2 and gdc 0.24 for it to work without hassle. It will complain about D_OS_VERSYM, which you should define as any arbitrary string. Like this:

Code: Select all

const char* cygwin_d_os_versym = "MyOS";
MessiahAndrw, you have already accomplished this.

Second:
Then have no standard library when building your actual kernel. That is, build with these flags to gdc: (written as it would be in a makefile)

Code: Select all

DFLAGS = -nostdlib -nodefaultlibs -g -mcmodel=kernel
Third:
The thing about gdc...it expects the runtime calls to be there and all 'magic' to be accounted for. You will need:
  • all of the typeinfo-ish stuff
  • the runtime stubs and
  • object.d (which is complete magic)
object.d and much of the runtime needs to be at the root of a include path. We were lazy, it is in the root of our source trunk.

In XOmB's code:
  • object.d - place at root of include path
  • builtins.d - you will need this, it allows gcc 'magic' for va_args. We don't use variadics in the kernel. Note: it looks for gcc/builtins.d in the include path.
  • std - some of the internals of the runtime. Should also be rooted in the include path.
  • runtime stubs - You know what... just use ours. BSD'd for your freedom. It can be anywhere, just has to be linked.
  • invariant.d - just more D runtime bull, copy from us. Can be anywhere, simply needs linked.
Just link everything together!

Eventually, in userland, you may need va_args as part of your user runtime (or your kernel, to each their own), which is COMPLETE magic in gdc as well. You will need to have std/stdarg.d, you can use the one from XOmB. The file, as you can see, has an empty implementation, yet, the compiler knows how to handle it automagically.

So... here is what you can do. Create a directory for your kernel runtime environment, add it to the include path (with the -I flag). Place all of the above in this directory and link all of them to your kernel's executable. You will have:

klibd
--object.d
--dstubs.d
--invariant.d
--gcc
----builtins.d
--std
----intrinsic.d
----stdarg.d
----c
------stdarg.d
----typeinfo
------ti_* (just steal from us!)

Will you be my guinea pig? :twisted:

When and if you confirm this to be workable, we can produce a D bare bones to release to the public domain.

Re: OS in D language

Posted: Sat Jan 31, 2009 1:10 am
by AndrewAPrice
Wilkie wrote: ----typeinfo
------ti_* (just steal from us!)
Wouldn't this be much easier to do using mixins since I see a lot of redundant code?

EDIT:

Okay, I had to add a few extra files (kernel/core/system.d and kernel/core/util.d).
It compiles without error, but when linking I get this:

Code: Select all

util.o: In function `_D4kernel4core4util4itoaFAaalZAa':
./source/kernel/core/util.d:374: undefined reference to `__umoddi3'
./source/kernel/core/util.d:375: undefined reference to `__udivdi3'
Errr..? Are these operators?

Re: OS in D language

Posted: Sat Jan 31, 2009 1:27 am
by quanganht
You guy are so fast! So, gdc huh ? I've been trying so hard with ldc ( and got nothing :? ). Well, it's good. Go for gdc now.

Re: OS in D language

Posted: Sat Jan 31, 2009 5:01 am
by AndrewAPrice
Finally!

I have it!
Here is my file layout:

Code: Select all

build.bat -- calls Cygwin's bash and executes the shell script
build.sh -- my shell script that does the compiling and linking
loader.asm -- my assembly stub
main.d
object.d
link.ld -- linker script
build/ -- where my object files go
core/dstubs.d ------- from here on down it's all runtime stuff
core/invariant.d
core/system.d
core/util.d
std/intrinsic.d
std/stdarg.d
std/c/stdarg.d
std/typeinfo/ti_*.d -- 35 files
gcc/builtins.d
I've built my first D kernel targeting elf-i586. GRUB loads the kernel at 1MB, then in my assembly stub I map the 4MB page starting at 3GB to point to 0, push the multiboot header info on to the stack, then call main.

Now my simple higher-half D kernel:

Code: Select all

extern(C) void main(uint magic, void *phymbinfo)
{
	ubyte *videoram = cast(ubyte *)0xb8000 + 0xC0000000;
	videoram[0] = 65;
	videoram[1] = 0x07;
}
prints a nice A in the top left of my screen :D Go D!

EDIT: And about those other errors, I had to link with libgcc.a. It's OS independent code that has a bunch of intrinsic arithmetic functions.

I'm going to edit my directory structure to separate the runtime from my kernel, and switch over to a makefile.

Can you tell me what features of the D language are not supported, and also what do I do about new/delete (where do I connect my allocator and such?)

Now to rewrite my kernel in D :D (It's probably a good thing doing a full rewrite once in a while to minimize bloat).

Re: OS in D language

Posted: Sun Feb 01, 2009 2:59 am
by quanganht
Is it really necessary to get GCC 4.1.2 ? (because i'm using 4.3.2 :lol: )

Re: OS in D language

Posted: Sun Feb 01, 2009 4:54 am
by AndrewAPrice
quanganht wrote:Is it really necessary to get GCC 4.1.2 ? (because i'm using 4.3.2 :lol: )
Well, yes and no.
The patch that comes with GDC can only be applied to certain versions of GCC, the latest being 4.1.x. If you really wanted to you could patch it yourself you could, on the first attempt I did try patching 4.3.2 and but it failed and I didn't want to hunt through the source manually so I just downloaded 4.1.2 and it worked without a flaw.

Re: OS in D language

Posted: Sun Feb 01, 2009 8:01 pm
by quanganht
MessiahAndrw wrote: I just downloaded 4.1.2 and it worked without a flaw.
So can you make an detailed Wiki page?
i'm stucking with expression.dmd.o: it says there is no complex.h
Edit: Killed it, but stuck at another point: iosfwd,cstdio... is missing.

EDIT 2: Oh silly me! I totally forgot to patch the top level src. That's why I keep stucking :lol: Trying agian !

Err. ld tells: can't find -lstdc++ ??? :?

Re: OS in D language

Posted: Mon Feb 02, 2009 12:11 am
by Wilkie
quanganht wrote:So can you make an detailed Wiki page?
Not completely necessary. The wiki already contains the information to build a gcc cross-compiler here. A link off of that page gives info about the 64-bit variant.

The INSTALL documentation given with gdc gives information about patching gcc.

Therefore, all relevant information is available, with the exception of the step I outlined in my previous post about editing (after configuration) one line to allow it to compile.

Re: OS in D language

Posted: Mon Feb 02, 2009 12:41 am
by Wilkie
MessiahAndrw wrote:Can you tell me what features of the D language are not supported, and also what do I do about new/delete (where do I connect my allocator and such?)
That is great news! Congrats on your achievement thus far. D is garbage collected, but the stubs have this capability disabled, so you'd probably just want to write the stubs for gc.malloc and gc.free (I believe) and then call them. A peek at a runtime implementation might help. Of course, you are edging a great debate to kernel heap allocations. My advice is to try and avoid them in your rewrite and just use directly a physical memory manager \ page allocator of your own design. This keeps you from doing "stupid things."

Doing this, you limit yourself, language-wise, to the static-subset of D. Anything that uses the D runtime stubs to allocate memory on your behalf cannot be used. You can do array slicing and casting pointers to arrays and the like, but you cannot create dynamic arrays or use dynamic array operations (that is, append). You cannot use classes and will probably prefer to use structs. You can, of course, use the entirety of the compile-time facilities (mixins, templates, and static conditionals), which is really where the power will come. You can use inline assembly. This includes the 'naked' directive (except in ldc currently, which is a huge drawback to porting our code).

You may prove me wrong.

For userland, you will have to port a C runtime (newlib) and\or a D runtime (phobos, tango). Look at reference implementations, much of which you can copy verbatim. They make calls to a malloc and are easily understood. From there, you can interface with your page allocator.

Also, you had to link to libgcc.a? That seems like a considerable trap. I wonder why you had to do this.