It was less than a year ago that I wrote about linker hacking the
runtime out of D code so that it could work as “better C” code, but things have already changed a lot since then. A
few days ago Walter Bright announced a new, improved
-betterC switch, which can now do a lot of the stuff that
needed ugly hacking before.
-betterC, and Why do I Need it?
The short answer is that most D programmers don’t need it. The longer answer is that it does two things: first, it restricts the language to a lower-level subset (that’s still higher-level than C), and, second, it changes the implementation of compiled code a little so that it only depends on the C runtime, and not the D runtime.
If you just want control over things like GC and runtime features for performance reasons, you can already get it
-betterC. You can read more about that in this GC series on the official blog, and in my previous post about the D runtime itself.
-betterC does provide is an intermediate
language that integrates very well with both C code and D code. Walter envisions this as a way for D to penetrate more
into parts of the software world that are still dominated by C. For example, practically all languages today still run
on top of a layer of operating system libraries that are written in C (and C++ in the Windows world). D’s runtime
itself depends on this layer, so D can’t ever replace C unless runtimeless programming is possible.
-betterC switch is a little controversial, and I agree
that things could be better in the future. But
here today, and ultimately we’re only going to figure out how to use D as a better C by trying it out. That’s why I
originally published that post about runtimeless D, even though it was a horrible hack.
There are two main ways betterC programming has improved since I last wrote about it. One pain point was the
over-dependence on runtime reflection in the language implementation, even for things like integer array comparisons
that could be implemented with just
memcmp(). A lot of work
has been done since then to replace reflection with templates, which is good news even for programmers who aren’t doing
low-level stuff. Lucia Cojocaru presented some of this work at
The other area of improvement is in the
itself. Back then there were only two places in the DMD compiler where
-betterC had any effect at all, so most runtime dependencies were left
in. Simply defining a struct, for example, would still cause the D compiler to insert
TypeInfo instances for runtime type information, which depend on base
class implementations that are defined in the D runtime library.
assert statements would still be implemented using a D runtime
implementation, not the C runtime implementation. These are the two most obvious problems that have been fixed.
-betterC Take Two
In that old post, I took some D code, compiled it, hacked out the runtime, and then linked it directly to some C code without the D runtime. Let’s see how things work now. Here’s the D code again:
And here’s the C code:
Here’s what happens now (on a GNU/Linux system):
Damn. So close. The D compiler has left in some exception handling data structures, even though
-betterC isn’t supposed to support exceptions. You’ll see I’m using the
new DMD beta, and there’s already an open bug report and pull
request for this kind of problem, so I expect it’ll be fixed soon.
I’ll update this post when it
Here’s a quick workaround for now (read the original linker hacking article for an explanation):
It might not look like much, but it’s a huge improvement. Thanks to all the developers who helped make it happen.