README.org

July 4, 2011 · View on GitHub

  • What is this? This is a compiler. When you run it, it compiles 'input.program' and produces a binary a.out.

The frontend is written in clojure, and the back-end is LLVM.

  • How to Run
  1. Install LLVM library.
  2. lein deps
  3. lein run

NOTE: The code assumes LLVM is at /opt/local/lib/libLLVM-2.9.dylib For different paths, update jna.library.path java property in native.clj.

  • Input Program Here our toy language is used as input into compiler frontend. #+BEGIN_SRC c func cos(Double) Double; func printf(...) Integer;

func bar() Integer { printf("foo"); return 3; }

func main() Integer { printf("hello %d", 3); printf("bar "); bar(); return 0; } #+END_SRC

  • Program Output
  1. The intermediate representation is printed.
  2. The object file and linked binary is created.
  3. Binary is executed, output is shown at bottom.

[[https://github.com/jasonjckn/llvm-clojure-bindings/raw/master/pic.png]]

  • How does it work?
  • parser.clj is for transforming Input=>AST (using clarsec, a combinator parser)
  • ast.clj is for transforming AST=>LLVM IR
  • main.clj is for LLVM IR=>object file=>linking.
  • llvm.clj contains needed llvm bindings for clojure.
  • native.clj is a thin JNA wrapper. It's like clj-native, but less efficient. (I couldn't get arrays of pointers working in clj-native.)

If input program is this: #+BEGIN_SRC func main() Integer { printf("foo"); printf("hello"); return 1; } #+END_SRC

AST looks like this: #+BEGIN_SRC ((:func main [] Integer (:call printf "foo") (:call printf "hello") (:return 1))) #+END_SRC

LLVM IR looks like this: #+BEGIN_SRC @0 = internal constant [4 x i8] c"foo\00" @1 = internal constant [9 x i8] c"hello %d\00"

define i32 @main() { %1 = call i32 (...)* @printf([9 x i8]* @1, i32 3) %2 = call i32 (...)* @printf([5 x i8]* @2) ret i32 1 } #+END_SRC

x86 Disassembly looks like this: #+BEGIN_SRC 0000000100000ef0 <_main>: 100000ef0: 50 push %rax 100000ef1: 48 8d 3d 3c 00 00 00 lea 0x3c(%rip),%rdi 100000ef8: be 03 00 00 00 mov $0x3,%esi 100000efd: 30 c0 xor %al,%al 100000eff: e8 26 00 00 00 callq 100000f2a <_printfstub>100000f04:488d3d32000000lea0x32(100000f0b:30c0xor100000f0d:e818000000callq100000f2a<printfstub> 100000f04: 48 8d 3d 32 00 00 00 lea 0x32(%rip),%rdi 100000f0b: 30 c0 xor %al,%al 100000f0d: e8 18 00 00 00 callq 100000f2a <_printfstub> 100000f12: 48 8d 3d 17 00 00 00 lea 0x17(%rip),%rdi 100000f19: 30 c0 xor %al,%al 100000f1b: e8 0a 00 00 00 callq 100000f2a <_printf$stub> 100000f20: 31 c0 xor %eax,%eax 100000f22: 5a pop %rdx 100000f23: c3 retq #+END_SRC