From b17531b79934e83fa6b40a945a19d3460dbd2b58 Mon Sep 17 00:00:00 2001 From: tali Date: Wed, 29 Nov 2023 16:21:35 -0500 Subject: [PATCH] add bytecode-like data type --- bin/main.ml | 14 +++++-- lib/dune | 2 +- lib/runtime/code.ml | 94 +++++++++++++++++++++++++++++++++++++++++++++ lib/runtime/dune | 3 ++ lib/spice.ml | 1 + 5 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 lib/runtime/code.ml create mode 100644 lib/runtime/dune diff --git a/bin/main.ml b/bin/main.ml index 5e1afae..f234568 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -3,7 +3,15 @@ let () = Logs.set_level (Some Logs.Debug); try - let syn = Spice.parse "val x = 3 val y = x + 1" in - let lir = Spice.compile syn in - Fmt.pr "%a\n" Spice.Lir.pp_entrypoint lir + let int n = Spice.Code.Cst_int (Int64.of_int n) in + let reg n = Spice.Code.Reg n in + + let l0 = Spice.Code.make_basic_block [ MUL (0, reg 1); RET ] in + let ep = + Spice.Code.make_basic_block + [ MOV (0, int 4); MOV (1, int 5); ADD (1, int 6); JMP l0 ] + in + + let prog = Spice.Code.make_program ep in + Fmt.pr "%a" Spice.Code.pp_program prog with Spice.Error msg -> Logs.err (fun m -> m "%s" msg) diff --git a/lib/dune b/lib/dune index 9f19893..f640544 100644 --- a/lib/dune +++ b/lib/dune @@ -1,3 +1,3 @@ (library (name spice) - (libraries fmt spice_syntax spice_lower)) + (libraries fmt spice_syntax spice_lower spice_runtime)) diff --git a/lib/runtime/code.ml b/lib/runtime/code.ml new file mode 100644 index 0000000..a688c54 --- /dev/null +++ b/lib/runtime/code.ml @@ -0,0 +1,94 @@ +type regidx = int + +type operand = + | Cst_nil + | Cst_true + | Cst_false + | Cst_int of int64 + | Reg of regidx + +type basic_block = { + mutable ins_builder : ins list; + mutable ins_list : ins list; + (* bc_pc : int *) + (* bc_len : int *) +} + +and ins = + | MOV of regidx * operand + | ADD of regidx * operand + | SUB of regidx * operand + | MUL of regidx * operand + | JMP of basic_block + | BRT of operand * basic_block * basic_block + | RET + +let make_basic_block ins_list = { ins_builder = List.rev ins_list; ins_list } + +let instructions bb = + (* memoize computing "rev ins_builder" by storing result in ins_list *) + if bb.ins_list = [] then bb.ins_list <- List.rev bb.ins_builder; + bb.ins_list + +let add_ins bb is = + (* "append" instruction by prepending to ins_builder list *) + bb.ins_builder <- is :: bb.ins_builder; + (* invalidate the cache *) + bb.ins_list <- [] + +type program = { entrypoint : basic_block } + +let make_program entrypoint = { entrypoint } + +(* pretty printing *) + +let pp_reg ppf r = Fmt.pf ppf "$%d" r + +let pp_operand ppf = function + | Cst_nil -> Fmt.pf ppf "nil" + | Cst_true -> Fmt.pf ppf "true" + | Cst_false -> Fmt.pf ppf "false" + | Cst_int n -> Fmt.pf ppf "#%s" (Int64.to_string n) + | Reg r -> pp_reg ppf r + +let pp_ins ~get_bb_name ppf = function + | MOV (l, r) -> Fmt.pf ppf "mov %a, %a" pp_reg l pp_operand r + | ADD (l, r) -> Fmt.pf ppf "add %a, %a" pp_reg l pp_operand r + | SUB (l, r) -> Fmt.pf ppf "sub %a, %a" pp_reg l pp_operand r + | MUL (l, r) -> Fmt.pf ppf "mul %a, %a" pp_reg l pp_operand r + | RET -> Fmt.pf ppf "ret" + | JMP l -> Fmt.pf ppf "jmp %s" (get_bb_name l) + | _ -> failwith "..." + +let pp_program ppf pr = + let ep = pr.entrypoint in + let basic_blocks = ref [ ep, "START" ] in + let work_list = ref [ ep ] in + let get_bb_name bb = + match List.find (fun (bb', _) -> bb == bb') !basic_blocks with + | _, name -> name + | exception Not_found -> + let name = Fmt.str "L%d" (List.length !basic_blocks - 1) in + basic_blocks := (bb, name) :: !basic_blocks; + work_list := bb :: !work_list; + name + in + let rec loop i = + match !work_list with + | [] -> () + | bb :: rest -> + work_list := rest; + if i > 0 then Fmt.pf ppf ","; + Fmt.pf ppf "%S:[" (get_bb_name bb); + List.iteri + (fun i is -> + if i > 0 then Fmt.pf ppf ","; + let str = Fmt.str "%a" (pp_ins ~get_bb_name) is in + Fmt.pf ppf "%S" str) + (instructions bb); + Fmt.pf ppf "]"; + loop (i + 1) + in + Fmt.pf ppf "{"; + loop 0; + Fmt.pf ppf "}" diff --git a/lib/runtime/dune b/lib/runtime/dune new file mode 100644 index 0000000..2d23ea7 --- /dev/null +++ b/lib/runtime/dune @@ -0,0 +1,3 @@ +(library + (name spice_runtime) + (libraries fmt)) diff --git a/lib/spice.ml b/lib/spice.ml index b25cee7..92ffb97 100644 --- a/lib/spice.ml +++ b/lib/spice.ml @@ -1,5 +1,6 @@ module Syn = Spice_syntax.Ast module Lir = Spice_lower.Lir +module Code = Spice_runtime.Code exception Error of string