dmd -betterC

Adam D. Ruppe via Digitalmars-d digitalmars-d at puremagic.com
Wed Jun 21 19:18:55 PDT 2017


On Wednesday, 21 June 2017 at 15:37:03 UTC, Adam D. Ruppe wrote:
> we have a *working* "better C".


I applied my two PRs along with Walter's patch and now have 
runtimeless D actually working.


Take a look at this:

----
// dmd still assumes these are present
// and they are in the C lib, but no without it
extern(C) void _Unwind_Resume() { asm { int 3; } }
extern(C) void __assert(bool c, in char* msg) {}


struct Foo {
	int x;
	char y;
	Foo* next;

	~this() {
     		printf("goodbye world %d\n", x);
	}
}

enum Test {
	a, b
}

extern (C) int main(char** argv, int argc) {
	scope(exit) printf("cruel world\n");
	try {
		Foo foo;
		foo.x = 10;

		int[6] buffer;
		int[] bar = buffer[1 .. 4];

		printf("hello world %d\n", foo.x);
	} finally {
		printf("sweet\n");
	}
	//assert(argc > 4, "foo");
	return 0;
}

void printf(T...)(string a, T t) {
	write(a);
	char[16] buffer;
	foreach(arg; t)
		write(intToString(arg, buffer[]));
}


char[] intToString(int i, char[] buffer) {
	int pos = cast(int) buffer.length - 1;

	if(i == 0) {
		buffer[pos] = '0';
		pos--;
	}

	while(pos > 0 && i) {
		buffer[pos] = (i % 10) + '0';
		pos--;
		i /= 10;
	}

	return buffer[pos + 1 .. $];
}


void write(in char[] a) {
	auto sptr = a.ptr;
	auto slen = a.length;
	size_t fd = 1;
	version(D_InlineAsm_X86)
	asm {
		mov ECX, sptr;
		mov EDX, slen;
		mov EBX, fd;
		mov EAX, 4; // sys_write
		int 0x80;
	}
	else version(D_InlineAsm_X86_64)
	asm {
		mov RSI, sptr;
		mov RDX, slen;
		mov RDI, fd;
		mov RAX, 1; // sys_write
		syscall;
	}
}

extern(C) void _start() {
	size_t code = main(null, 0);

	version(D_InlineAsm_X86)
	asm {
		mov EAX, 1; // sys_exit
		mov EBX, code;
		int 0x80;
	}
	else version(D_InlineAsm_X86_64)
	asm {
		mov RAX, 60; // sys_exit
		mov RDI, code;
		syscall;
	}
}
----


# Note that the -I is not necessary if your compiler is
# actually installed; I just need it here since it is a
# hacked up compiler
src/dmd hello.d -I../druntime/import -betterC -release -c
ld hello.o -nostdlib
$ ls -lh a.out
-rwxr-xr-x 1 me users 2.5K Jun 21 22:13 a.out
$ ldd a.out
         not a dynamic executable



Wow. If you remember my old minimal.d, it took about 15 lines of 
stub runtime to even get it to compile.... and was still 3.3 K in 
my best attempt.

Now it works - including structs with dtors (if you have my two 
PRs merged) - and makes a tiny 2.5 K exe (on Linux here), with 
zero dependencies. This could run on bare metal. I've done that 
before, but never this simple.

* * *

What about using the C library?

---
import core.stdc.stdio;

struct Test {
	int x;
	int y;

	this(int x, int y) {
		this.x = y;
		this.y = y;
		printf("Constructed\n");
		foo();
	}

	~this() {
		printf("Destructed\n");
		foo();
	}

	void foo() {
		printf("Values are: %d, %d\n", x, y);
	}
}

extern(C) int main() {
	printf("Hello!\n");
	scope(exit) printf("Bye!\n");

	Test test = Test(10, 20);
	test.x += 45;
	test.foo();

	return 0;
}
---


Look at that - looks like a reasonably useful program, with 
structs, printing, members, even a destructor. How hard was it to 
build?


$ src/dmd hello2.d -betterC  -I../druntime/import
$ ./hello2
Hello!
Constructed
Values are: 20, 20
Values are: 65, 20
Destructed
Values are: 65, 20
Bye!

$ ls -lh hello2
-rwxr-xr-x 1 me users 11K Jun 21 22:18 hello2
$ ldd hello2
         linux-vdso.so.1 (0x00007ffe4b3fc000)
         libpthread.so.0 => /lib64/libpthread.so.0 
(0x00007fabb78f6000)
         libm.so.6 => /lib64/libm.so.6 (0x00007fabb75f3000)
         librt.so.1 => /lib64/librt.so.1 (0x00007fabb73ea000)
         libdl.so.2 => /lib64/libdl.so.2 (0x00007fabb71e6000)
         libgcc_s.so.1 => /usr/lib64/libgcc_s.so.1 
(0x00007fabb6fd0000)
         libc.so.6 => /lib64/libc.so.6 (0x00007fabb6c04000)
         /lib64/ld-linux-x86-64.so.2 (0x00005595dec5f000)


11K executable, linking in standard C stuff.


With my PRs combined with Walter's, we actually have something 
useful here.

Note that I used -release on the top program because otherwise 
there's linker errors for array bounds checks. I am 100% happy 
with this behavior.


More information about the Digitalmars-d mailing list