I have ported a large part of the State compiler and the burg code-generator to be able to compile and assemble this simple test case:
(define |main| (lambda () 1))
It may seem trivial but to compile this example requires the implementation of:
- The parser framework (ometa) in Church
- The sexp parser for reading State source files
- The ometa-based macro expander for expanding State macros
- The AST conversion pass which constructs lexical scope information and tracks free variables
- The final compilation phase which creates a tree of pseudo-instruction objects
and that’s just the State compiler, the code generator has the following parts
- general framework for tracking liveness, register allocation and matching pseudo-instructions to machine instructions
- implementation of pseudo-instructions and rules for using them
- x86-specific description of the machine registers
- backend that produces actual machine code according to opcode formats (handling different addressing modes etc)
I have managed to generate the correct machine code bytes for this test case (but I don’t generate an ELF object file yet), here is the disassembled output:
cmalu% ndisasm -u burg_asm.output
00000000 55 push ebp
00000001 89E5 mov ebp,esp
00000003 68BBBB7707 push dword 0x777bbbb
00000008 68FFFF0000 push dword 0xffff
0000000D B80E000000 mov eax,0xe
00000012 8D4DF8 lea ecx,[ebp-0x8]
00000015 8901 mov [ecx],eax
00000017 B801000000 mov eax,0x1
0000001C 89C0 mov eax,eax
0000001E 59 pop ecx
0000001F 59 pop ecx
00000020 5D pop ebp
00000021 C3 ret
Which looks like the output produced by the lisp implementation of the system (except for a change in the stack marker constant):
00000027 :
27: 55 push %ebp
28: 89 e5 mov %esp,%ebp
2a: 68 bb bb aa aa push $0xaaaabbbb
2f: 68 ff ff 00 00 push $0xffff
34: b8 0e 00 00 00 mov $0xe,%eax
39: 8d 4d f8 lea -0x8(%ebp),%ecx
3c: 89 01 mov %eax,(%ecx)
3e: b8 01 00 00 00 mov $0x1,%eax
43: 89 c0 mov %eax,%eax
45: 59 pop %ecx
46: 59 pop %ecx
47: 5d pop %ebp
48: c3 ret