Hitchikers Guide to Porting Phobos / D Runtime to other architectures

Iain Buclaw ibuclaw at gdcproject.org
Tue Jan 7 17:15:32 PST 2014


2014/1/8 Mike <none at none.com>:
> On Tuesday, 7 January 2014 at 21:52:54 UTC, Dwhatever wrote:
>>>
>>> What CPU/MCU are you targeting?  Are you building for bare-metal?
>>
>>
>> Yes, for bare metal, no OS, nothing.
>>
>> I think I have to specify my target architecture and CPU otherwise the
>> compiler cannot know that I'm cross compiling for ARM. -march= -mcpu= will
>> not work for me.
>>
>> I'm trying to compile a simple stand alone object file.
>>
>> class TestClass
>> {
>>     ubyte member;
>>
>>     this(ubyte m) { member = m; }
>>     ubyte Get() { return member; }
>> };
>>
>>
>> extern(C) void main()
>> {
>>     // stack class
>>    scope test = new TestClass(0);
>>
>>    // simple inline asm test
>>    __asm("mov r0,#1;
>>           mov r1,#2", "~{r0,r1}");
>> }
>>
>> This test should be simple enough I thought but it turned out that to
>> compile and link this, D requires almost everything from the runtime.
>>
>> So the challenge is, compile and link the simple code above targeting ARM
>> using LDC, no OS allowed.
>
>
> First of all, there's no such thing as a class allocated on the stack in D.
> See here ( http://dlang.org/deprecate.html#scope for allocating classes on
> the stack).  You have to go with structs if you want that feature, but there
> are other ways like Scoped(T), RefeCounted(T), scope(exit), etc...  It feels
> as little half-ass to do things this way, but D is quite powerful, and an
> alternate, elegant solution is probably just waiting to be discovered.
>

Yeah, I'd like to block that proposal for deprecation until Scoped(T)
doesn't rely on DMD-specific NRVO behaviour.


> Anyway, once you add the word "class" or "struct" you release an avalanche
> of snowballing required runtime stuff that you are likely not even using,
> directly or indirectly, in your program. And if using --gc-sections in your
> linker, it all just gets stripped out in the end. I was trying to articulate
> that here (http://forum.dlang.org/post/zewevdmburppufkjxdje@forum.dlang.org)
>

If you use a struct, it generates typeinfo and initialiser symbols
that go on the comdat on the basis that you *may* access the typeinfo
at runtime.

These are weak decls so the linker merges/removes duplicates.  There's
currently no solution in which the compiler decides whether to omit
sending the symbols to object file, but this can be worked upon.

> IMO this is a problem with the compiler, not D, and LDC suffers from it much
> more than GDC. Iain Buclaw recently made a change to GDC
> (http://forum.dlang.org/post/mailman.3.1387377012.2938.d.gnu@puremagic.com)
> that allowed me to reduce my object.d to 140 lines, and with an accompanying
> malloc and free, I was able to create classes. I don't know what the change
> was, but it was most beneficial (Thanks Iain!). I hope the LDC folks can do
> the same, but I probably need to file an enhancement request and make a case
> for it.
>

I could have sworn that I spoke to David about this a couple months
back, and it was in LDC already - unless they have some rules as to
whether a static array literal is loaded on the stack or heap...

> I'm sorry I can't share my code at the moment; I haven't decided yet where
> to put it.  I was studying Adam Ruppe's minimal X86 port last night and
> found it most useful (Thumbs Up!), but with a 2000 line object.d, it's
> stretching the word "minimal", at least when compared with C. But if you
> really want all the cool stuff D has to offer, this is probably what will be
> required in the end.
>

So it's only double the size of C runtime (crt.o, crtend.o :-)

I think the best logical steps to go down, is that you should write a
replacement for the core library functions that the compiler
implicitly calls (_d_arrayliteralX, _d_arraycopy, _d_newclass,
_d_newitemT, etc), but omit using the TypeInfo parameter.  Once you
feel that it is ready, then we can add a switch into the compiler
that:
1) Doesn't generate typeinfo
2) Passes a null pointer as the typeinfo parameter to the Druntime
library calls.

After testing and verifying it's all going sound, I'd be happy to omit
the typeinfo altogether from the compiler side.

However, before we get there, this will have some interesting hurdles
to go over, for instance:

Object _d_newclass(const ClassInfo ci)  ->  Object _d_newclass()

Means that:
1) There's no way to tell the GC what we are allocating (eg: classes
with no pointer fields require no scanning).
However being bare bones, you probably won't mind this.  There is no
stop-the-world GC in the background.

2) The new'd class is not default initialised _d_newclass  (no
typeinfo, no known initialiser).
So either you accept as a reasonable trade-off that there's no default
initialisation of classes in bare-bones, or we alter the compiler
codegen to take care of the default initialisation *after* calling
_d_newclass.

Others will have similar problems to consider.


More information about the Digitalmars-d mailing list