Can dmd compile with my own runtime library?

Huang F Guan gdxxhg at gmail.com
Thu Aug 23 04:15:01 PDT 2007


Alexander Panek Wrote:

> Huang F Guan wrote:
> > Hi, I'm an operating system developer. I've written a win32-compatible and POSIX operating system, just for fun, but it can run many windows api programs. My system is written in C, it is not readable and diffcult to manage. Now I am looking for the new techniques to rewrite this os.
> > 
> > I've ever thought for an own compiler and linker, it is so complicated to develop an advanced one. But DMD did it, the D language almost satisfied what I need. Yes, you see, I am trying to use it to develop an operating system in D language, and maybe it will be the first one written in D language. 
> > 
> > While I was using C++ developing an os, the compiler can output the platform-independent code. But DMD compiler can not do this, because it needs a runtime library based on the present platform. 
> > 
> > I have tried gdc, but I failed too. It prints the error below when I link:
> > 
> > ld: warning: cannot find entry symbol _mainCRTStartup; defaulting to 00401000
> > hello.o(.text+0x18):hello.d: undefined reference to `_Dmodule_ref'
> > hello.o(.text+0x23):hello.d: undefined reference to `_Dmodule_ref'
> > hello.o(.data+0x0):hello.d: undefined reference to `_D10ModuleInfo6__vtblZ'
> > hello.o(.data+0x30):hello.d: undefined reference to `_D6object12__ModuleInfoZ'
> > 
> > Now I am wondering how can I link a platform-independent executable file? 
> > Do I need to rewrite the runtime library? 
> > Or just I need to write a tiny runtime library like gc, moduleinit, object?
> > 
> > I hope you can help me solve these puzzles, thanks!
> > 
> 
> If you take a closer look at OCD's or Titan's build process, you'll 
> eventually find out how to build your kernel. First thing: if you load 
> your kernel with Grub, you need an entry point in an Assembly file (or 
> at least I didn't succeed creating a valid Multiboot header inside a D 
> file), like here:
> 
> http://trac.brainsware.org/ocd/browser/branches/ocd-take2/ocd/nucleus/entry.asm
> 
> This file is proven to work. If you want to use it, please go ahead.. as 
> well as with 'all the other' (isn't so much yet, eh) OCD code, of course. :)
> 
> Anyways, your D entry point has to be extern(C) to remove the D name 
> mangling, afterwards you can operate in a D environment as much as you 
> please. Be sure to use structs where you can, as (dynamically 
> instantiated) classes can lead to GC invocations. Also avoid dynamic 
> arrays or associative arrays.. but Frits mentioned that all already I think.
> 
> Would be nice if you keep us informed about your progress!
> 
> Kind regards,
> Alex


Hi, What you said is the basic things, I have all done now. I had a look at the OCD kernel code, there's no class using in it, but intead of struct. 

I think a class is important for wrapping the functions, and template is useful too. 

I wrote an object.d, see below:

module object;


/// Standard boolean type.
alias bool bit;

/**
* An unsigned integral type large enough to span the memory space. Use for
* array indices and pointer offsets for maximal portability to
* architectures that have different memory address ranges. This is
* analogous to C's size_t.
*/
alias ulong size_t;

/**
* A signed integral type large enough to span the memory space. Use for
* pointer differences and for size_t differences for maximal portability to
* architectures that have different memory address ranges. This is
* analogous to C's ptrdiff_t.
*/
alias long ptrdiff_t;

alias ulong hash_t;


/******************
 * All D class objects inherit from Object.
 */
class Object
{
    void print()
    {
	//printf("%.*s\n", toString());
    }
    char[] toString()
    {
    	//return null; //test
    	while(1)continue;
	return this.classinfo.name;
    }
    /**
     * Compute hash function for Object.
     */
    hash_t toHash()
    {
	// BUG: this prevents a compacting GC from working, needs to be fixed
    	while(1)continue;
	return cast(hash_t)cast(void *)this;
    }
    int opCmp(Object o)
    {
	//test
    	while(1)continue;
	return 1;
	//throw new Error("need opCmp for class " ~ this.classinfo.name);
    }

    int opEquals(Object o)
    {
    	while(1)continue;
	return cast(int)(this is o);
    }
}

/**
 * Information about an interface.
 * A pointer to this appears as the first entry in the interface's vtbl[].
 */
struct Interface
{
    ClassInfo classinfo;	/// .classinfo for this interface (not for containing class)
    void *[] vtbl;
    int offset;			/// offset to Interface 'this' from Object 'this'
}
/**
 * Array of pairs giving the offset and type information for each
 * member in an aggregate.
 */
struct OffsetTypeInfo
{
    size_t offset;	/// Offset of member from start of object
    //TypeInfo ti;	/// TypeInfo for this member
}

class ClassInfo : Object
{
    byte[] init;		/** class static initializer
				 * (init.length gives size in bytes of class)
				 */
    char[] name;		/// class name
    void *[] vtbl;		/// virtual function pointer table
    Interface[] interfaces;	/// interfaces this class implements
    ClassInfo base;		/// base class
    void *destructor;
    void (*classInvariant)(Object);
    uint flags;
    //	1:			// IUnknown
    //	2:			// has no possible pointers into GC memory
    //	4:			// has offTi[] member
    //	8:			// has constructors
    void *deallocator;
    OffsetTypeInfo[] offTi;
    void function(Object) defaultConstructor;	// default Constructor

    /*************
     * Search all modules for ClassInfo corresponding to classname.
     * Returns: null if not found
     */
    static ClassInfo find(char[] classname)
    {
    	while(1)
		continue;
	//foreach (m; ModuleInfo.modules())
	//{
	//    //writefln("module %s, %d", m.name, m.localClasses.length);
	//    foreach (c; m.localClasses)
	//    {
	//	//writefln("\tclass %s", c.name);
	//	if (c.name == classname)
	//	    return c;
	 //   }
	//}
	return null;
    }

    /********************
     * Create instance of Object represented by 'this'.
     */
    Object create()
    {
	if (flags & 8 && !defaultConstructor)
	    return null;
	Object o = _d_newclass(this);
	if (flags & 8 && defaultConstructor)
	{
	    defaultConstructor(o);
	}
	return o;
    }
}

extern(C):
Object _d_newclass(Object ci)
{
    void *p;
    p = cast(void*)0x22222222;
    //if (ci.flags & 1)			// if COM object
    //{
	//p = std.c.stdlib.malloc(ci.init.length);
	//if (!p)
	//    _d_OutOfMemory();
    //}
    // Initialize it
    //(cast(byte*)p)[0 .. ci.init.length] = ci.init[];
    //printf("initialization done\n");
    return cast(Object)p;
}

=========END=========
I used DMD to compile it, a fatal error occured and the DMD-self exited.



More information about the Digitalmars-d mailing list