diff --git a/src/backend/brilisp.scm b/src/backend/brilisp.scm index 8bcb3cf..da1f9bb 100644 --- a/src/backend/brilisp.scm +++ b/src/backend/brilisp.scm @@ -34,12 +34,17 @@ (args (rest header)) (instrs (rest (rest expr)))) `((name . ,name) - (type . ,type) + (type . ,(gen-type type)) (args . ,(map-vec gen-arg args)) (instrs . ,(map-vec gen-instr instrs))))) (define (gen-arg arg) - `((name . ,(first arg)) (type . ,(second arg)))) + `((name . ,(first arg)) (type . ,(gen-type (second arg))))) + +(define (gen-type type) + (if (list? type) + `((,(first type) . ,(gen-type (second type)))) + type)) (define (gen-instr instr) (define (const? instr) @@ -50,20 +55,20 @@ (let ((to (second instr)) (from (third instr))) `((op . const) - (type . ,(second to)) + (type . ,(gen-type (second to))) (dest . ,(first to)) (value . ,(second from))))) (define (value? instr) (and (eq? (first instr) 'set) (memq (first (third instr)) - '(add mul sub div eq lt gt le ge not and or)))) + '(add mul sub div eq lt gt le ge not and or alloc load ptradd id)))) (define (gen-value-instr instr) (let ((to (second instr)) (from (third instr))) `((op . ,(first from)) - (type . ,(second to)) + (type . ,(gen-type (second to))) (dest . ,(first to)) (args . ,(list->vector (rest from)))))) @@ -81,7 +86,7 @@ (let ((to (second instr)) (from (third instr))) `((op . call) - (type . ,(second to)) + (type . ,(gen-type (second to))) (dest . ,(first to)) (funcs . ,(vector (second from))) (args . ,(list->vector (rest (rest from))))))) @@ -113,6 +118,13 @@ (define (gen-nop-instr instr) `((op . nop))) + (define (store? instr) + (eq? (first instr) 'store)) + + (define (gen-store-instr instr) + `((op . store) + (args . ,(list->vector (rest instr))))) + (cond ((const? instr) (gen-const-instr instr)) ((value? instr) (gen-value-instr instr)) @@ -122,6 +134,7 @@ ((label? instr) (gen-label-instr instr)) ((br? instr) (gen-br-instr instr)) ((nop? instr) (gen-nop-instr instr)) + ((store? instr) (gen-store-instr instr)) (else (error "unknown instruction: " instr)))) (bril (rest (read))) diff --git a/src/backend/llvm.py b/src/backend/llvm.py index cb94734..5b73357 100644 --- a/src/backend/llvm.py +++ b/src/backend/llvm.py @@ -4,8 +4,6 @@ References: 1. https://github.com/eliben/pykaleidoscope/ 2. https://llvm.org/docs/tutorial/ - -Assumes BRIL is in SSA form """ import sys @@ -47,7 +45,12 @@ def generate(self, bril_prog): self.gen_function(fn) def gen_type(self, type): - if type == "int": + if isinstance(type, dict): + if "ptr" in type: + return self.gen_type(type["ptr"]).as_pointer() + else: + raise CodegenError(f"Unknown type {type}") + elif type == "int": return ir.IntType(32) elif type == "void": return ir.VoidType() @@ -158,29 +161,76 @@ def gen_comp(instr): ), ) + def gen_alloc(instr): + pointer_type = self.gen_type(instr.type) + self.declare_var(pointer_type, instr.dest) + self.gen_symbol_store( + instr.dest, + self.builder.alloca( + pointer_type.pointee, size=self.gen_var(instr.args[0]) + ), + ) + + def gen_store(instr): + ptr = self.gen_symbol_load(instr.args[0]) + self.builder.store(self.gen_var(instr.args[1]), ptr) + + def gen_load(instr): + self.declare_var(self.gen_type(instr.type), instr.dest) + ptr = self.gen_symbol_load(instr.args[0]) + self.gen_symbol_store(instr.dest, self.builder.load(ptr)) + + def gen_ptradd(instr): + self.declare_var(self.gen_type(instr.type), instr.dest) + self.gen_symbol_store( + instr.dest, + self.builder.gep( + self.gen_var(instr.args[0]), + [self.gen_var(arg) for arg in instr["args"][1:]], + ), + ) + + def gen_id(instr): + self.declare_var(self.gen_type(instr.type), instr.dest) + self.gen_symbol_store(instr.dest, self.gen_symbol_load(instr.args[0])) + for instr in instrs: - if "label" in instr: - gen_label(instr) - elif self.builder.block.is_terminated: - pass # Do not codegen for unreachable code - elif instr.op == "nop": - pass - elif instr.op == "jmp": - gen_jmp(instr) - elif instr.op == "br": - gen_br(instr) - elif instr.op == "call": - gen_call(instr) - elif instr.op == "ret": - gen_ret(instr) - elif instr.op == "const": - gen_const(instr) - elif instr.op in value_ops: - gen_value(instr) - elif instr.op in cmp_ops: - gen_comp(instr) - else: - raise CodegenError(f"Unknown op in the instruction: {dict(instr)}") + try: + if "label" in instr: + gen_label(instr) + elif self.builder.block.is_terminated: + pass # Do not codegen for unreachable code + elif instr.op == "nop": + pass + elif instr.op == "jmp": + gen_jmp(instr) + elif instr.op == "br": + gen_br(instr) + elif instr.op == "call": + gen_call(instr) + elif instr.op == "ret": + gen_ret(instr) + elif instr.op == "const": + gen_const(instr) + elif instr.op == "alloc": + gen_alloc(instr) + elif instr.op == "store": + gen_store(instr) + elif instr.op == "load": + gen_load(instr) + elif instr.op == "ptradd": + gen_ptradd(instr) + elif instr.op == "id": + gen_id(instr) + elif instr.op in value_ops: + gen_value(instr) + elif instr.op in cmp_ops: + gen_comp(instr) + else: + raise CodegenError(f"Unknown op in the instruction: {dict(instr)}") + except Exception as e: + print(f"Exception: {e}; in instruction {instr}:") + raise e def gen_function_prototype(self, fn): funcname = fn.name diff --git a/src/backend/tests/brilisp/access.out b/src/backend/tests/brilisp/access.out new file mode 100644 index 0000000..06e5182 --- /dev/null +++ b/src/backend/tests/brilisp/access.out @@ -0,0 +1 @@ +8989898 diff --git a/src/backend/tests/brilisp/access.sexp b/src/backend/tests/brilisp/access.sexp new file mode 100644 index 0000000..e003131 --- /dev/null +++ b/src/backend/tests/brilisp/access.sexp @@ -0,0 +1,20 @@ +(brilisp + (bril-define ((print int) (n int))) + + (bril-define ((main int)) + (set (inc int) (const 1)) + (set (v int) (const 4545454)) + (set (max int) (const 8989898)) + (set (p (ptr int)) (alloc v)) + (set (count int) (const 0)) + + (label lbl) + (set (count int) (add count inc)) + (store p v) + (set (val int) (load p)) + (set (loop bool) (ge count max)) + (br loop end lbl) + + (label end) + (set (tmp int) (call print count)) + (ret tmp))) diff --git a/src/backend/tests/brilisp/access_many.out b/src/backend/tests/brilisp/access_many.out new file mode 100644 index 0000000..06e5182 --- /dev/null +++ b/src/backend/tests/brilisp/access_many.out @@ -0,0 +1 @@ +8989898 diff --git a/src/backend/tests/brilisp/access_many.sexp b/src/backend/tests/brilisp/access_many.sexp new file mode 100644 index 0000000..0527599 --- /dev/null +++ b/src/backend/tests/brilisp/access_many.sexp @@ -0,0 +1,21 @@ +(brilisp + (bril-define ((print int) (n int))) + + (bril-define ((main int)) + (set (inc int) (const 1)) + (set (v int) (const 4545454)) + (set (max int) (const 8989898)) + (set (arr (ptr int)) (alloc v)) + (set (count int) (const 0)) + + (label lbl) + (set (arr_i (ptr int)) (ptradd arr count)) + (set (count int) (add count inc)) + (store arr_i v) + (set (val int) (load arr_i)) + (set (loop bool) (ge count max)) + (br loop end lbl) + + (label end) + (set (tmp int) (call print count)) + (ret tmp))) diff --git a/src/backend/tests/brilisp/access_ptr.out b/src/backend/tests/brilisp/access_ptr.out new file mode 100644 index 0000000..06e5182 --- /dev/null +++ b/src/backend/tests/brilisp/access_ptr.out @@ -0,0 +1 @@ +8989898 diff --git a/src/backend/tests/brilisp/access_ptr.sexp b/src/backend/tests/brilisp/access_ptr.sexp new file mode 100644 index 0000000..89d3528 --- /dev/null +++ b/src/backend/tests/brilisp/access_ptr.sexp @@ -0,0 +1,22 @@ +(brilisp + (bril-define ((print int) (n int))) + + (bril-define ((main int)) + (set (inc int) (const 1)) + (set (v int) (const 4545)) + (set (max int) (const 8989898)) + (set (p (ptr int)) (alloc v)) + (set (arr (ptr (ptr int))) (alloc v)) + (set (count int) (const 0)) + + (label lbl) + (set (arr_i (ptr (ptr int))) (ptradd arr count)) + (set (count int) (add count inc)) + (store arr p) + (set (val (ptr int)) (load arr_i)) + (set (loop bool) (ge count max)) + (br loop end lbl) + + (label end) + (set (tmp int) (call print count)) + (ret tmp))) diff --git a/src/backend/tests/brilisp/alloc.out b/src/backend/tests/brilisp/alloc.out new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/src/backend/tests/brilisp/alloc.out @@ -0,0 +1 @@ +1 diff --git a/src/backend/tests/brilisp/alloc.sexp b/src/backend/tests/brilisp/alloc.sexp new file mode 100644 index 0000000..519f349 --- /dev/null +++ b/src/backend/tests/brilisp/alloc.sexp @@ -0,0 +1,25 @@ +(brilisp + (bril-define ((print int) (n int))) + + (bril-define ((print_bool int) (b bool)) + (set (T int) (const 1)) + (set (F int) (const 0)) + (br b print_true print_false) + (label print_true) + (set (tmp int) (call print T)) + (ret tmp) + (label print_false) + (set (tmp int) (call print F)) + (ret tmp)) + + (bril-define ((main int)) + (set (v int) (const 4)) + (set (o1 int) (const 1)) + (set (bp (ptr bool)) (alloc v)) + (set (bp2 (ptr bool)) (ptradd bp o1)) + (set (b bool) (const true)) + (store bp b) + (store bp2 b) + (set (b bool) (load bp2)) + (set (tmp int) (call print_bool b)) + (ret tmp))) diff --git a/src/backend/tests/brilisp/arr_sum.out b/src/backend/tests/brilisp/arr_sum.out new file mode 100644 index 0000000..c3f407c --- /dev/null +++ b/src/backend/tests/brilisp/arr_sum.out @@ -0,0 +1 @@ +55 diff --git a/src/backend/tests/brilisp/arr_sum.sexp b/src/backend/tests/brilisp/arr_sum.sexp new file mode 100644 index 0000000..3271eb4 --- /dev/null +++ b/src/backend/tests/brilisp/arr_sum.sexp @@ -0,0 +1,28 @@ +(brilisp + (bril-define ((print int) (n int))) + + (bril-define ((main int)) + (set (len int) (const 10)) + (set (arr (ptr int)) (alloc len)) + (set (sum int) (const 0)) + (set (idx int) (const 0)) + (set (one int) (const 1)) + + (label init) + (set (arr_i (ptr int)) (ptradd arr idx)) + (set (idx int) (add idx one)) + (store arr_i idx) + (set (loop bool) (lt idx len)) + (br loop init calc) + + (label calc) + (set (idx int) (sub idx one)) + (set (arr_i (ptr int)) (ptradd arr idx)) + (set (v int) (load arr_i)) + (set (sum int) (add sum v)) + (set (loop bool) (ge idx one)) + (br loop calc out) + + (label out) + (set (tmp int) (call print sum)) + (ret tmp))) diff --git a/src/backend/tests/brilisp/fib.out b/src/backend/tests/brilisp/fib.out new file mode 100644 index 0000000..a787364 --- /dev/null +++ b/src/backend/tests/brilisp/fib.out @@ -0,0 +1 @@ +34 diff --git a/src/backend/tests/brilisp/fib.sexp b/src/backend/tests/brilisp/fib.sexp new file mode 100644 index 0000000..f71334c --- /dev/null +++ b/src/backend/tests/brilisp/fib.sexp @@ -0,0 +1,37 @@ +(brilisp + (bril-define ((print int) (n int))) + + (bril-define ((main int)) + (set (one int) (const 1)) + (set (i int) (const 2)) + (set (i_m_1 int) (const 1)) + (set (i_m_2 int) (const 0)) + (set (n int) (const 10)) + (set (seq (ptr int)) (alloc n)) + + (set (v int) (const 0)) + (store seq v) + (set (v int) (const 1)) + (set (p (ptr int)) (ptradd seq i_m_1)) + (store p v) + + (label calc_i) + (set (p_m_2 (ptr int)) (ptradd seq i_m_2)) + (set (p_m_1 (ptr int)) (ptradd seq i_m_1)) + (set (v_m_2 int) (load p_m_2)) + (set (v_m_1 int) (load p_m_1)) + (set (v int) (add v_m_1 v_m_2)) + (set (p (ptr int)) (ptradd seq i)) + (store p v) + (set (i_m_1 int) (add i_m_1 one)) + (set (i_m_2 int) (add i_m_2 one)) + (set (i int) (add i one)) + (set (loop bool) (le i n)) + (br loop calc_i out) + + (label out) + (set (i int) (sub n one)) + (set (p (ptr int)) (ptradd seq i)) + (set (v int) (load p)) + (set (tmp int) (call print v)) + (ret tmp))) diff --git a/src/backend/tests/brilisp/mem_id.out b/src/backend/tests/brilisp/mem_id.out new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/src/backend/tests/brilisp/mem_id.out @@ -0,0 +1 @@ +7 diff --git a/src/backend/tests/brilisp/mem_id.sexp b/src/backend/tests/brilisp/mem_id.sexp new file mode 100644 index 0000000..8006aad --- /dev/null +++ b/src/backend/tests/brilisp/mem_id.sexp @@ -0,0 +1,13 @@ +(brilisp + (bril-define ((print int) (n int))) + + (bril-define ((main int)) + (set (v int) (const 1)) + (set (p (ptr int)) (alloc v)) + (set (v int) (const 7)) + (store p v) + + (set (p2 (ptr int)) (id p)) + (set (v int) (load p)) + (set (tmp int) (call print v)) + (ret tmp))) diff --git a/src/backend/tests/brilisp/ptr_call.out b/src/backend/tests/brilisp/ptr_call.out new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/tests/brilisp/ptr_call.sexp b/src/backend/tests/brilisp/ptr_call.sexp new file mode 100644 index 0000000..5287ff6 --- /dev/null +++ b/src/backend/tests/brilisp/ptr_call.sexp @@ -0,0 +1,9 @@ +(brilisp + (bril-define ((funcA void) (p (ptr int))) + (ret)) + + (bril-define ((main void)) + (set (five int) (const 5)) + (set (x (ptr int)) (alloc five)) + (set (tmp void) (call funcA x)) + (ret))) diff --git a/src/backend/tests/brilisp/ptr_ret.out b/src/backend/tests/brilisp/ptr_ret.out new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/tests/brilisp/ptr_ret.sexp b/src/backend/tests/brilisp/ptr_ret.sexp new file mode 100644 index 0000000..acc00ea --- /dev/null +++ b/src/backend/tests/brilisp/ptr_ret.sexp @@ -0,0 +1,9 @@ +(brilisp + (bril-define ((ident (ptr int)) (p (ptr int))) + (ret p)) + + (bril-define ((main void)) + (set (a int) (const 9)) + (set (b (ptr int)) (alloc a)) + (set (c (ptr int)) (call ident b)) + (ret))) diff --git a/src/backend/tests/brilisp/transpose.out b/src/backend/tests/brilisp/transpose.out new file mode 100644 index 0000000..7d5c1b4 --- /dev/null +++ b/src/backend/tests/brilisp/transpose.out @@ -0,0 +1,9 @@ +0 +1 +2 +2 +3 +4 +4 +5 +6 diff --git a/src/backend/tests/brilisp/transpose.sexp b/src/backend/tests/brilisp/transpose.sexp new file mode 100644 index 0000000..fc910d9 --- /dev/null +++ b/src/backend/tests/brilisp/transpose.sexp @@ -0,0 +1,85 @@ +(brilisp + (bril-define ((print int) (n int))) + + (bril-define ((elem int) (i int) (j int)) + (set (two int) (const 2)) + (set (j int) (mul j two)) + (set (i int) (add i j)) + (ret i)) + + (bril-define ((arr_read int) (arr (ptr (ptr int))) (i int) (j int)) + (set (p (ptr (ptr int))) (ptradd arr i)) + (set (r (ptr int)) (load p)) + (set (p (ptr int)) (ptradd r j)) + (set (v int) (load p)) + (ret v)) + + (bril-define ((arr_write void) (arr (ptr (ptr int))) (i int) (j int) (v int)) + (set (p (ptr (ptr int))) (ptradd arr i)) + (set (r (ptr int)) (load p)) + (set (p (ptr int)) (ptradd r j)) + (store p v) + (ret)) + + (bril-define ((main void)) + (set (one int) (const 1)) + (set (three int) (const 3)) + (set (arr (ptr (ptr int))) (alloc three)) + (set (i int) (const 0)) + (set (j int) (const 0)) + + (label init_row) + (set (p (ptr (ptr int))) (ptradd arr i)) + (set (r (ptr int)) (alloc three)) + (store p r) + (label init_col) + (set (v int) (call elem i j)) + (set (tmp void) (call arr_write arr i j v)) + (set (j int) (add j one)) + (set (j_loop bool) (lt j three)) + (br j_loop init_col cont1) + (label cont1) + (set (j int) (const 0)) + (set (i int) (add i one)) + (set (i_loop bool) (lt i three)) + (br i_loop init_row cont2) + + (label cont2) + (set (i int) (const 0)) + (set (j int) (const 0)) + + (label calc_row) + (set (j int) (add i one)) + (label calc_col) + (set (vij int) (call arr_read arr i j)) + (set (vji int) (call arr_read arr j i)) + (set (tmp void) (call arr_write arr i j vji)) + (set (tmp void) (call arr_write arr j i vij)) + (set (j int) (add j one)) + (set (j_loop bool) (le j three)) + (br j_loop calc_col cont3) + (label cont3) + (set (j int) (const 0)) + (set (i int) (add i one)) + (set (i_loop bool) (le i three)) + (br i_loop calc_row cont4) + + (label cont4) + (set (i int) (const 0)) + (set (j int) (const 0)) + + (label out_row) + (label out_col) + (set (v int) (call arr_read arr i j)) + (set (tmp int) (call print v)) + (set (j int) (add j one)) + (set (j_loop bool) (lt j three)) + (br j_loop out_col cont5) + (label cont5) + (set (j int) (const 0)) + (set (i int) (add i one)) + (set (i_loop bool) (lt i three)) + (br i_loop out_row cont6) + + (label cont6) + (ret)))