Advertisement
amitsp21

Untitled

Dec 19th, 2018
860
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 37.76 KB | None | 0 0
  1. (* generates LLVM IR from AP++ source code *)
  2.  
  3. module L = Llvm
  4. module A = Ast
  5. open Sast
  6.  
  7. module StringMap = Map.Make(String)
  8.  
  9. (* translate : Sast.program -> Llvm.module *)
  10. let translate (globals, functions) =
  11.   let context    = L.global_context () in
  12.  
  13.   (* Create the LLVM compilation module into which
  14.      we will generate code *)
  15.   let the_module = L.create_module context "AP_PlusPlus" in
  16.  
  17.   (* Get types from the context *)
  18.   let i32_t      = L.i32_type    context
  19.   and i8_t       = L.i8_type     context
  20.   and i1_t       = L.i1_type     context
  21.   and float_t    = L.double_type context
  22.   and str_t      = L.pointer_type (L.i8_type context)
  23.   and void_t     = L.void_type   context
  24.   and list_t t   = L.struct_type context [| L.pointer_type (L.i32_type context); (L.pointer_type t) |]
  25.   and ptr_list_t t = L.pointer_type (L.struct_type context [| L.pointer_type (L.i32_type context); (L.pointer_type t) |])
  26.   in
  27.  
  28.   (* Return the LLVM type for a AP++ type *)
  29.   let rec ltype_of_typ = function
  30.       A.Int   -> i32_t
  31.     | A.Bool  -> i1_t
  32.     | A.Float -> float_t
  33.     | A.String -> str_t
  34.     | A.Void  -> void_t
  35.     | A.List t -> list_t (ltype_of_typ t)
  36.   in
  37.   let type_str t = match t with
  38.        A.Int -> "int"
  39.      | A.Bool -> "bool"
  40.      | A.Float -> "float"
  41.      | A.String -> "str"
  42.      | _ -> raise (Failure "Invalid string map key type")
  43.   in
  44.   (* Create a map of global variables after creating each *)
  45.   let global_vars : L.llvalue StringMap.t =
  46.     let global_var m (t, n) =
  47.       let init = match t with
  48.          A.Float -> L.const_float (ltype_of_typ t) 0.0
  49.        | _ -> L.const_int (ltype_of_typ t) 0
  50.       in StringMap.add n (L.define_global n init the_module) m in
  51.     List.fold_left global_var StringMap.empty globals in
  52.  
  53.   let printf_t : L.lltype =
  54.       L.var_arg_function_type i32_t [| L.pointer_type i8_t |] in
  55.   let printf_func : L.llvalue =
  56.       L.declare_function "printf" printf_t the_module in
  57.  
  58.    (* LLVM insists each basic block end with exactly one "terminator"
  59.     instruction that transfers control.  This function runs "instr builder"
  60.     if the current block does not already have a terminator.  Used,
  61.     e.g., to handle the "fall off the end of the function" case. *)
  62.    let add_terminal builder instr =
  63.      match L.block_terminator (L.insertion_block builder) with
  64.        Some _ -> ()
  65.      | None -> ignore (instr builder) in
  66.  
  67.     let build_while builder build_predicate build_body func_def =
  68.        let pred_bb = L.append_block context "while" func_def in
  69.        ignore(L.build_br pred_bb builder);
  70.  
  71.        let body_bb = L.append_block context "while_body" func_def in
  72.        add_terminal (build_body (L.builder_at_end context body_bb)) (L.build_br pred_bb);
  73.  
  74.        let pred_builder = L.builder_at_end context pred_bb in
  75.        let bool_val = build_predicate pred_builder in
  76.  
  77.        let merge_bb = L.append_block context "merge" func_def in
  78.        ignore(L.build_cond_br bool_val body_bb merge_bb pred_builder);
  79.        L.builder_at_end context merge_bb
  80.    in
  81.  
  82.    let build_if builder build_predicate build_then_stmt build_else_stmt func_def =
  83.        let bool_val = build_predicate builder in
  84.        let merge_bb = L.append_block context "merge" func_def in
  85.        let build_br_merge = L.build_br merge_bb in (* partial function *)
  86.  
  87.        let then_bb = L.append_block context "then" func_def in
  88.        add_terminal (build_then_stmt (L.builder_at_end context then_bb))
  89.        build_br_merge;
  90.  
  91.        let else_bb = L.append_block context "else" func_def in
  92.        add_terminal (build_else_stmt (L.builder_at_end context else_bb))
  93.        build_br_merge;
  94.  
  95.        ignore(L.build_cond_br bool_val then_bb else_bb builder);
  96.        L.builder_at_end context merge_bb
  97.   in
  98.   (* ltype list_get(list a, i32_t index) *)
  99.   let list_get : L.llvalue StringMap.t =
  100.     let list_get_ty m typ =
  101.        let ltype = (ltype_of_typ typ) in
  102.        let def_name = (type_str typ) in
  103.        let def = L.define_function ("list_get" ^ def_name) (L.function_type ltype [| L.pointer_type (list_t ltype); i32_t |]) the_module in
  104.        let build = L.builder_at_end context (L.entry_block def) in
  105.        let list_ptr = L.build_alloca (L.pointer_type (list_t ltype)) "list_ptr_alloc" build in
  106.        let _ = L.build_store (L.param def 0) list_ptr build in
  107.        let idx_ptr = L.build_alloca i32_t "idx_alloc" build in
  108.        let _ = L.build_store (L.param def 1) idx_ptr build in
  109.        let list_load = L.build_load list_ptr "list_load" build in
  110.        let list_array_ptr = L.build_struct_gep list_load 1 "list_array_ptr" build in
  111.        let list_array_load = L.build_load list_array_ptr "array_load" build in
  112.        let idx = L.build_load idx_ptr "idx_load" build in
  113.        let list_array_element_ptr = L.build_gep list_array_load [| idx |] "list_arry_element_ptr" build in
  114.        let element_val = L.build_load list_array_element_ptr "list_array_element_ptr" build in
  115.        let _ = L.build_ret element_val build in
  116.        StringMap.add def_name def m in
  117.   List.fold_left list_get_ty StringMap.empty [ A.Bool; A.Int; A.Float; A.String ] in
  118.  
  119.   (* void list_set(list a, i32_t idx, ltype value) *)
  120.   let list_set : L.llvalue StringMap.t =
  121.     let list_set_ty m typ =
  122.      let ltype = (ltype_of_typ typ) in
  123.      let def_name = (type_str typ) in
  124.      let def = L.define_function ("list_set" ^ def_name) (L.function_type void_t [| L.pointer_type (list_t ltype); i32_t; ltype |]) the_module in
  125.      let build = L.builder_at_end context (L.entry_block def) in
  126.      let list_ptr = L.build_alloca (L.pointer_type (list_t ltype)) "list_ptr_alloc" build in
  127.      ignore(L.build_store (L.param def 0) list_ptr build);
  128.      let list_load = L.build_load list_ptr "list_load" build in
  129.      let list_array_ptr = L.build_struct_gep list_load 1 "list_array_ptr" build in
  130.      let list_array_load = L.build_load list_array_ptr "list_array_load" build in
  131.      let idx_element_ptr = L.build_gep list_array_load [| L.param def 1 |] "list_arry_next_element_ptr" build in
  132.      let _ = L.build_store (L.param def 2) idx_element_ptr build in
  133.      let _ = L.build_ret_void build in
  134.      StringMap.add def_name def m in
  135.   List.fold_left list_set_ty StringMap.empty [ A.Bool; A.Int; A.Float; A.String ] in
  136.  
  137.   (* void list_push(list, ltype value) *)
  138.   let list_push : L.llvalue StringMap.t =
  139.     let list_push_ty m typ =
  140.      let ltype = (ltype_of_typ typ) in
  141.      let def_name = (type_str typ) in
  142.      let def = L.define_function ("list_push" ^ def_name) (L.function_type void_t [| L.pointer_type (list_t ltype); ltype |]) the_module in
  143.      let build = L.builder_at_end context (L.entry_block def) in
  144.      let list_ptr = L.build_alloca (L.pointer_type (list_t ltype)) "list_ptr_alloc" build in
  145.      ignore(L.build_store (L.param def 0) list_ptr build);
  146.      let valPtr = L.build_alloca ltype "val_alloc" build in
  147.      ignore(L.build_store (L.param def 1) valPtr build);
  148.      let list_load = L.build_load list_ptr "list_load" build in
  149.      let list_array_ptr = L.build_struct_gep list_load 1 "list_array_ptr" build in
  150.      let list_array_load = L.build_load list_array_ptr "list_array_load" build in
  151.      let list_size_ptr_ptr = L.build_struct_gep list_load 0 "list_size_ptr_ptr" build in
  152.      let list_size_ptr = L.build_load list_size_ptr_ptr "list_size_ptr" build in
  153.      let list_size = L.build_load list_size_ptr "list_size" build in
  154.      let next_index = list_size in
  155.      let next_element_ptr = L.build_gep list_array_load [| next_index |] "list_arry_next_element_ptr" build in
  156.      let next_size = L.build_add list_size (L.const_int i32_t 1) "inc_size" build in
  157.      let _ = L.build_store next_size list_size_ptr build in
  158.      let _ = L.build_store (L.build_load valPtr "val" build) next_element_ptr build in
  159.      let _ = L.build_ret_void build in
  160.      StringMap.add def_name def m in
  161.   List.fold_left list_push_ty StringMap.empty [ A.Bool; A.Int; A.Float; A.String ] in
  162.  
  163.   (* ltype list_pop(list a) *)
  164.   let list_pop : L.llvalue StringMap.t =
  165.     let list_pop_ty m typ =
  166.        let ltype = (ltype_of_typ typ) in
  167.        let def_name = (type_str typ) in
  168.        let def = L.define_function ("list_pop" ^ def_name) (L.function_type ltype [| L.pointer_type (list_t ltype) |]) the_module in
  169.        let build = L.builder_at_end context (L.entry_block def) in
  170.        let list_ptr = L.build_alloca (L.pointer_type (list_t ltype)) "list_ptr_alloc" build in
  171.        ignore(L.build_store (L.param def 0) list_ptr build);
  172.        let list_load = L.build_load list_ptr "list_load" build in
  173.        let list_array_ptr = L.build_struct_gep list_load 1 "list_array_ptr" build in
  174.        let list_array_load = L.build_load list_array_ptr "list_array_load" build in
  175.        let list_size_ptr_ptr = L.build_struct_gep list_load 0 "list_size_ptr_ptr" build in
  176.        let list_size_ptr = L.build_load list_size_ptr_ptr "list_size_ptr" build in
  177.        let list_size = L.build_load list_size_ptr "list_size" build in
  178.        let list_sizeMin1 = L.build_sub list_size (L.const_int i32_t 1) "dec_size" build in
  179.        let last_element_ptr = L.build_gep list_array_load [| list_sizeMin1 |] "list_arry_next_element_ptr" build in
  180.        let last_element_val = L.build_load last_element_ptr "list_arry_next_element" build in
  181.        let _ = L.build_store list_sizeMin1 list_size_ptr build in
  182.        let _ = L.build_ret last_element_val build in
  183.     StringMap.add def_name def m in
  184.   List.fold_left list_pop_ty StringMap.empty [ A.Bool; A.Int; A.Float; A.String ] in
  185.  
  186.   (* i32_t list_size(list a) *)
  187.   let list_size : L.llvalue StringMap.t =
  188.     let list_size_ty m typ =
  189.      let ltype = (ltype_of_typ typ) in
  190.      let def_name = (type_str typ) in
  191.      let def = L.define_function ("list_size" ^ def_name) (L.function_type i32_t [| L.pointer_type (list_t ltype) |]) the_module in
  192.      let build = L.builder_at_end context (L.entry_block def) in
  193.      let list_ptr = L.build_alloca (L.pointer_type (list_t ltype)) "list_ptr_alloc" build in
  194.      ignore(L.build_store (L.param def 0) list_ptr build);
  195.      let list_load = L.build_load list_ptr "list_load" build in
  196.      let list_size_ptr_ptr = L.build_struct_gep list_load 0 "list_size_ptr_ptr" build in
  197.      let list_size_ptr = L.build_load list_size_ptr_ptr "list_size_ptr" build in
  198.      let list_size = L.build_load list_size_ptr "list_size" build in
  199.      ignore(L.build_ret list_size build);
  200.      StringMap.add def_name def m in
  201.   List.fold_left list_size_ty StringMap.empty [ A.Bool; A.Int; A.Float; A.String ] in
  202.  
  203.   let init_list builder list_ptr list_type =
  204.     (* initialize size to 0 *)
  205.     let sizePtrPtr = L.build_struct_gep list_ptr 0 "list_size_ptr" builder in
  206.        let sizePtr = L.build_alloca i32_t "list_size" builder in
  207.        let _ = L.build_store (L.const_int i32_t 0) sizePtr builder in
  208.        ignore(L.build_store sizePtr sizePtrPtr builder);
  209.     (* initialize array *)
  210.     let list_array_ptr = L.build_struct_gep list_ptr 1 "list.arry" builder in
  211.      (* TODO: allocate nothing and have list grow dynamically as necessary when pushing into the list *)
  212.       let p = L.build_array_alloca (ltype_of_typ list_type) (L.const_int i32_t 1028) "p" builder in
  213.       ignore(L.build_store p list_array_ptr builder);
  214.   in
  215.  
  216.   let list_slice : L.llvalue StringMap.t =
  217.      let list_slice_ty m typ =
  218.         let ltype = (ltype_of_typ typ) in
  219.         let def_name = (type_str typ) in
  220.         let def = L.define_function ("list_slice" ^ def_name) (L.function_type void_t [| ptr_list_t ltype; ptr_list_t ltype; i32_t; i32_t |]) the_module in
  221.         let build = L.builder_at_end context (L.entry_block def) in
  222.  
  223.         let list_ptr_ptr = L.build_alloca (ptr_list_t ltype) "list_ptr_alloc" build in
  224.         let _ = L.build_store (L.param def 0) list_ptr_ptr build in
  225.         let list_ptr = L.build_load list_ptr_ptr "list_ptr_ptr" build in
  226.  
  227.         let list_ptr_ptr2 = L.build_alloca (ptr_list_t ltype) "list_ptr_alloc2" build in
  228.         let _ = L.build_store (L.param def 1) list_ptr_ptr2 build in
  229.         let list_ptr2 = L.build_load list_ptr_ptr2 "list_ptr_ptr2" build in
  230.  
  231.         let idx_ptr1 = L.build_alloca i32_t "idx_alloc" build in
  232.         let _ = L.build_store (L.param def 2) idx_ptr1 build in
  233.         let idx1 = L.build_load idx_ptr1 "idx_load" build in
  234.  
  235.         let idx_ptr2 = L.build_alloca i32_t "idx_alloc" build in
  236.         let _ = L.build_store (L.param def 3) idx_ptr2 build in
  237.         let idx2 = L.build_load idx_ptr2 "idx_load" build in
  238.  
  239.         (* loop counter init: 0 *)
  240.         let loop_cnt_ptr = L.build_alloca i32_t "loop_cnt" build in
  241.         let _ = L.build_store (L.const_int i32_t 0) loop_cnt_ptr build in
  242.         (* loop upper bound: j-i *)
  243.         let loop_upper_bound = L.build_sub idx2 idx1 "loop_upper_bound" build in
  244.         (* loop condition: cnt <= j-i *)
  245.         let loop_cond _builder =
  246.             L.build_icmp L.Icmp.Sle (L.build_load loop_cnt_ptr "loop_cnt" _builder) loop_upper_bound "loop_cond" _builder
  247.         in
  248.         (* assignment: b[cnt] = a[cnt + i] *)
  249.         let loop_body _builder =
  250.            let to_index = L.build_load loop_cnt_ptr "to_idx" _builder in
  251.            let from_index = L.build_add to_index idx1 "from_idx" _builder in
  252.            let get_val = L.build_call (StringMap.find (type_str typ) list_get) [| list_ptr; from_index |] "list_get" _builder in
  253.            let _ = L.build_call (StringMap.find (type_str typ) list_push) [| list_ptr2; get_val |] "" _builder in
  254.            let index_incr = L.build_add (L.build_load loop_cnt_ptr "loop_cnt" _builder) (L.const_int i32_t 1) "loop_itr" _builder in
  255.            let _ = L.build_store index_incr loop_cnt_ptr _builder in
  256.            _builder
  257.         in
  258.         let while_builder = build_while build loop_cond loop_body def in
  259.         ignore(L.build_ret_void while_builder);
  260.         StringMap.add def_name def m
  261.      in
  262.      List.fold_left list_slice_ty StringMap.empty [ A.Bool; A.Int; A.Float; A.String ] in
  263.  
  264.   (* i32_t list_find(list, val) *)
  265.   let list_find : L.llvalue StringMap.t =
  266.     let list_find_ty m typ =
  267.        let ltype = (ltype_of_typ typ) in
  268.        let def_name = (type_str typ) in
  269.        let def = L.define_function ("list_find" ^ def_name) (L.function_type i32_t [| L.pointer_type (list_t ltype); ltype |]) the_module in
  270.        let build = L.builder_at_end context (L.entry_block def) in
  271.        let list_ptr = L.build_alloca (L.pointer_type (list_t ltype)) "list_ptr_alloc" build in
  272.        ignore(L.build_store (L.param def 0) list_ptr build);
  273.        let find_value_ptr = L.build_alloca ltype "find_val_alloc" build in
  274.        ignore(L.build_store (L.param def 1) find_value_ptr build);
  275.        let find_value = L.build_load find_value_ptr "find_val" build in
  276.        let list_load = L.build_load list_ptr "list_load" build in
  277.        let list_size_ptr_ptr = L.build_struct_gep list_load 0 "list_size_ptr_ptr" build in
  278.        let list_size_ptr = L.build_load list_size_ptr_ptr "list_size_ptr" build in
  279.        let list_size = L.build_load list_size_ptr "list_size" build in
  280.        let loop_idx_ptr = L.build_alloca i32_t "loop_cnt" build in
  281.        let _ = L.build_store (L.const_int i32_t 0) loop_idx_ptr build in
  282.        let loop_upper_bound = list_size in
  283.        let loop_cond _builder =
  284.           L.build_icmp L.Icmp.Slt (L.build_load loop_idx_ptr "loop_iter_cnt" _builder) loop_upper_bound "loop_cond" _builder
  285.        in
  286.        let loop_body _builder =
  287.          let index = L.build_load loop_idx_ptr "to_idx" _builder in
  288.          let get_val = L.build_call (StringMap.find (type_str typ) list_get) [| list_load; index |] "list_get" _builder in
  289.          let if_cond _builder2 =
  290.             (match typ with
  291.                 A.Int | A.Bool -> L.build_icmp L.Icmp.Eq
  292.               | A.Float -> L.build_fcmp L.Fcmp.Oeq
  293.               | _ -> raise (Failure ("list_find does not support this list type"))
  294.             ) get_val find_value "if_cond" _builder2
  295.          in
  296.          let if_body _builder2 = ignore(L.build_ret index _builder2); _builder2 in
  297.          let else_body _builder2 = ignore(L.const_int i32_t 0); _builder2 in
  298.          let if_builder = build_if _builder if_cond if_body else_body def in
  299.          let index_incr = L.build_add (L.build_load loop_idx_ptr "loop_idx" if_builder) (L.const_int i32_t 1) "loop_itr" if_builder in
  300.          let _ = L.build_store index_incr loop_idx_ptr if_builder in
  301.          if_builder
  302.        in
  303.        let while_builder = build_while build loop_cond loop_body def in
  304.        ignore(L.build_ret (L.const_int i32_t (-1)) while_builder);
  305.        StringMap.add def_name def m in
  306.      List.fold_left list_find_ty StringMap.empty [ A.Bool; A.Int; A.Float ] in
  307.  
  308.   (* void list_remove(list, typ value) *)
  309.   let list_remove : L.llvalue StringMap.t =
  310.     let list_remove_ty m typ =
  311.      let ltype = (ltype_of_typ typ) in
  312.      let def_name = (type_str typ) in
  313.      let def = L.define_function ("list_remove" ^ def_name) (L.function_type void_t [| L.pointer_type (list_t ltype); ltype |]) the_module in
  314.      let build = L.builder_at_end context (L.entry_block def) in
  315.      let list_ptr = L.build_alloca (L.pointer_type (list_t ltype)) "list_ptr_alloc" build in
  316.      ignore(L.build_store (L.param def 0) list_ptr build);
  317.      let remove_value_ptr = L.build_alloca ltype "rem_val_ptr" build in
  318.      ignore(L.build_store (L.param def 1) remove_value_ptr build);
  319.      let remove_value = L.build_load remove_value_ptr "rem_val" build in
  320.      let list_load = L.build_load list_ptr "list_load" build in
  321.      let list_size_ptr_ptr = L.build_struct_gep list_load 0 "list_size_ptr_ptr" build in
  322.      let list_size_ptr = L.build_load list_size_ptr_ptr "list_size_ptr" build in
  323.      let list_size = L.build_load list_size_ptr "list_size" build in
  324.      let listFindIndex = L.build_call (StringMap.find (type_str typ) list_find) [| list_load; remove_value |] "list_find" build in
  325.      let list_find_if_cond _builder =
  326.          L.build_icmp L.Icmp.Sge listFindIndex (L.const_int i32_t 0) "loop_cond" _builder in
  327.      let list_else_body _builder = ignore(L.const_int i32_t 0); _builder in
  328.      let list_find_if_body _builder =
  329.         let loop_idx_ptr = L.build_alloca i32_t "loop_cnt_ptr" _builder in
  330.         let loop_start_idx = L.build_add listFindIndex (L.const_int i32_t 1) "loop_start_idx" _builder in
  331.         let _ = L.build_store loop_start_idx loop_idx_ptr _builder in
  332.         let loop_upper_bound = list_size in
  333.         let loop_cond _builder =
  334.            L.build_icmp L.Icmp.Slt (L.build_load loop_idx_ptr "loop_cnt" _builder) loop_upper_bound "loop_cond" _builder
  335.         in
  336.         let loop_body _builder =
  337.           let cur_index = L.build_load loop_idx_ptr "cur_idx" _builder in
  338.           let shiftto_index = L.build_sub cur_index (L.const_int i32_t 1) "shift_to_idx" _builder in
  339.           let get_val = L.build_call (StringMap.find (type_str typ) list_get) [| list_load; cur_index |] "list_get" _builder in
  340.           let _ = L.build_call (StringMap.find (type_str typ) list_set) [| list_load; shiftto_index; get_val |] "" _builder in
  341.           let index_incr = L.build_add cur_index (L.const_int i32_t 1) "loop_itr" _builder in
  342.           let _ = L.build_store index_incr loop_idx_ptr _builder in
  343.           _builder
  344.         in
  345.         let while_builder = build_while _builder loop_cond loop_body def in
  346.         let size_dec = L.build_sub list_size (L.const_int i32_t 1) "size_dec" while_builder in
  347.         let _ = L.build_store size_dec list_size_ptr while_builder in
  348.         ignore(L.build_ret_void while_builder); while_builder
  349.      in
  350.      let if_builder = build_if build list_find_if_cond list_find_if_body list_else_body def in
  351.      let _ = L.build_ret_void if_builder in
  352.      StringMap.add def_name def m in
  353.   List.fold_left list_remove_ty StringMap.empty [ A.Bool; A.Int; A.Float ] in
  354.  
  355.   (* void list_insert(list, int idx, typ value) *)
  356.   let list_insert : L.llvalue StringMap.t =
  357.     let list_insert_ty m typ =
  358.      let ltype = (ltype_of_typ typ) in
  359.      let def_name = (type_str typ) in
  360.      let def = L.define_function ("list_insert" ^ def_name) (L.function_type void_t [| L.pointer_type (list_t ltype); i32_t; ltype |]) the_module in
  361.      let build = L.builder_at_end context (L.entry_block def) in
  362.  
  363.      let list_ptr = L.build_alloca (L.pointer_type (list_t ltype)) "list_ptr_alloc" build in
  364.      ignore(L.build_store (L.param def 0) list_ptr build);
  365.      let list_load = L.build_load list_ptr "list_load" build in
  366.  
  367.      let insertidx_ptr = L.build_alloca i32_t "insert_idx_ptr" build in
  368.      ignore(L.build_store (L.param def 1) insertidx_ptr build);
  369.      let insertIdx = L.build_load insertidx_ptr "insert_idx" build in
  370.      
  371.      let insertValPtr = L.build_alloca ltype "insert_val_ptr" build in
  372.      ignore(L.build_store (L.param def 2) insertValPtr build);
  373.      let insertVal = L.build_load insertValPtr "insert_val" build in
  374.  
  375.      let list_size_ptr_ptr = L.build_struct_gep list_load 0 "list_size_ptr_ptr" build in
  376.      let list_size_ptr = L.build_load list_size_ptr_ptr "list_size_ptr" build in
  377.      let list_size = L.build_load list_size_ptr "list_size" build in
  378.      let loop_idx_ptr = L.build_alloca i32_t "loop_cnt_ptr" build in
  379.      let lastIndex = L.build_sub list_size (L.const_int i32_t 1) "last_index" build in
  380.      let _ = L.build_store lastIndex loop_idx_ptr build in
  381.      let decto_index = insertIdx in
  382.      let loop_cond _builder =
  383.         L.build_icmp L.Icmp.Sge (L.build_load loop_idx_ptr "loop_cnt" _builder) decto_index "loop_cond" _builder
  384.      in
  385.      let loop_body _builder =
  386.        let cur_index = L.build_load loop_idx_ptr "cur_idx" _builder in
  387.        let shiftto_index = L.build_add cur_index (L.const_int i32_t 1) "shift_to_idx" _builder in
  388.        let get_val = L.build_call (StringMap.find (type_str typ) list_get) [| list_load; cur_index |] "list_get" _builder in
  389.        let _ = L.build_call (StringMap.find (type_str typ) list_set) [| list_load; shiftto_index; get_val |] "" _builder in
  390.        let indexDec = L.build_sub cur_index (L.const_int i32_t 1) "loop_itr" _builder in
  391.        let _ = L.build_store indexDec loop_idx_ptr _builder in
  392.        _builder
  393.      in
  394.      let while_builder = build_while build loop_cond loop_body def in
  395.      let _ = L.build_call (StringMap.find (type_str typ) list_set) [| list_load; insertIdx; insertVal |] "" while_builder in
  396.      let sizeInc = L.build_add list_size (L.const_int i32_t 1) "size_inc" while_builder in
  397.      let _ = L.build_store sizeInc list_size_ptr while_builder in
  398.      ignore(L.build_ret_void while_builder);
  399.      StringMap.add def_name def m in
  400.   List.fold_left list_insert_ty StringMap.empty [ A.Bool; A.Int; A.Float ] in
  401.  
  402.  (* void list_insert(list, int idx, typ value) *)
  403.   let list_reverse : L.llvalue StringMap.t =
  404.     let list_reverse_ty m typ =
  405.      let ltype = (ltype_of_typ typ) in
  406.      let def_name = (type_str typ) in
  407.      let def = L.define_function ("list_reverse" ^ def_name) (L.function_type void_t [| L.pointer_type (list_t ltype) |]) the_module in
  408.      let build = L.builder_at_end context (L.entry_block def) in
  409.  
  410.      let list_ptr = L.build_alloca (L.pointer_type (list_t ltype)) "list_ptr_alloc" build in
  411.      ignore(L.build_store (L.param def 0) list_ptr build);
  412.      let list_load = L.build_load list_ptr "list_load" build in
  413.  
  414.      let list_size_ptr_ptr = L.build_struct_gep list_load 0 "list_size_ptr_ptr" build in
  415.      let list_size_ptr = L.build_load list_size_ptr_ptr "list_size_ptr" build in
  416.      let list_size = L.build_load list_size_ptr "list_size" build in
  417.  
  418.      let leftPtr = L.build_alloca i32_t "left_idx" build in
  419.      let _ = L.build_store (L.const_int i32_t 0) leftPtr build in
  420.      let rightPtr = L.build_alloca i32_t "right_idx" build in
  421.      let _ = L.build_store (L.build_sub list_size (L.const_int i32_t 1) "tmp" build) rightPtr build in
  422.  
  423.      let while_cond _builder = L.build_icmp L.Icmp.Slt
  424.         (L.build_load leftPtr "left_idx" _builder)
  425.         (L.build_load rightPtr "right_idx" _builder) "while_cond" _builder
  426.      in
  427.      let while_body _builder =
  428.         let left_idx = (L.build_load leftPtr "left_idx" _builder) in
  429.         let right_idx = (L.build_load rightPtr "right_idx" _builder) in
  430.         let get_left_val = L.build_call (StringMap.find (type_str typ) list_get) [| list_load; left_idx |] "list_get" _builder in
  431.         let get_right_val = L.build_call (StringMap.find (type_str typ) list_get) [| list_load; right_idx |] "list_get" _builder in
  432.         let _ = L.build_call (StringMap.find (type_str typ) list_set) [| list_load; left_idx; get_right_val |] "" _builder in
  433.         let _ = L.build_call (StringMap.find (type_str typ) list_set) [| list_load; right_idx; get_left_val |] "" _builder in
  434.         let _ = L.build_store (L.build_add left_idx (L.const_int i32_t 1) "tmp" _builder) leftPtr _builder in
  435.         let _ = L.build_store (L.build_sub right_idx (L.const_int i32_t 1) "tmp" _builder) rightPtr _builder in
  436.         _builder
  437.       in
  438.       let while_builder = build_while build while_cond while_body def in
  439.       ignore(L.build_ret_void while_builder);
  440.       StringMap.add def_name def m in
  441.   List.fold_left list_reverse_ty StringMap.empty [ A.Bool; A.Int; A.Float ] in
  442.  
  443.   (* Define each function (arguments and return type) so we can
  444.      call it even before we've created its body *)
  445.   let function_decls : (L.llvalue * sfunc_decl) StringMap.t =
  446.     let function_decl m fdecl =
  447.       let name = fdecl.sfname
  448.       and formal_types = Array.of_list (List.map (fun (t,_) -> ltype_of_typ t) fdecl.sformals)
  449.       in let ftype = L.function_type (ltype_of_typ fdecl.styp) formal_types in
  450.       StringMap.add name (L.define_function name ftype the_module, fdecl) m in
  451.       List.fold_left function_decl StringMap.empty functions in
  452.  
  453.   (* Fill in the body of the given function *)
  454.   let build_function_body fdecl =
  455.     let (the_function, _) = StringMap.find fdecl.sfname function_decls in
  456.     let builder = L.builder_at_end context (L.entry_block the_function) in
  457.  
  458.     let int_format_str = L.build_global_stringptr "%d\n" "fmt" builder in
  459.     let float_format_str = L.build_global_stringptr "%g\n" "fmt" builder in
  460.     let str_format_str = L.build_global_stringptr "%s\n" "fmt" builder in
  461.  
  462.     (* Construct the function's "locals": formal arguments and locally
  463.        declared variables.  Allocate each on the stack, initialize their
  464.        value, if appropriate, and remember their values in the "locals" map *)
  465.     let local_vars =
  466.       let add_formal m (t, n) p =
  467.         L.set_value_name n p;
  468.     let local = L.build_alloca (ltype_of_typ t) n builder in
  469.     ignore(
  470.       match t with
  471.         A.List list_type -> init_list builder local list_type
  472.       | _ -> ()
  473.     );
  474.     ignore (L.build_store p local builder);
  475.     StringMap.add n local m
  476.  
  477.       (* Allocate space for any locally declared variables and add the
  478.        * resulting registers to our map *)
  479.       and add_local m (t, n) =
  480.   let local_var = L.build_alloca (ltype_of_typ t) n builder in
  481.   ignore(
  482.     match t with
  483.       A.List list_type -> init_list builder local_var list_type
  484.     | _ -> ()
  485.   );
  486.   StringMap.add n local_var m
  487.       in
  488.       let formals = List.fold_left2 add_formal StringMap.empty fdecl.sformals
  489.           (Array.to_list (L.params the_function)) in
  490.       List.fold_left add_local formals fdecl.slocals
  491.     in
  492.  
  493.     (* Return the value for a variable or formal argument.
  494.        Check local names first, then global names *)
  495.     let lookup n = try StringMap.find n local_vars
  496.                    with Not_found -> StringMap.find n global_vars
  497.  
  498.     in
  499.     (* Construct code for an expression; return its value *)
  500.     let rec expr builder ((_, e) : sexpr) = match e with
  501.         SILiteral i  -> L.const_int i32_t i
  502.       | SBLiteral b  -> L.const_int i1_t (if b then 1 else 0)
  503.       | SFLiteral l -> L.const_float float_t l
  504.       | SSLiteral s -> L.build_global_stringptr (s^"\x00") "strptr" builder
  505.       | SNoexpr     -> L.const_int i32_t 0
  506.       | SId s       -> L.build_load (lookup s) s builder
  507.       | SAssign (s, e) -> let e' = expr builder e in
  508.                           ignore(L.build_store e' (lookup s) builder); e'
  509.       | SBinop ((A.Float, _ ) as e1, op, e2) ->
  510.         let e1' = expr builder e1
  511.         and e2' = expr builder e2 in
  512.         (match op with
  513.           A.Add     -> L.build_fadd
  514.         | A.Sub     -> L.build_fsub
  515.         | A.Mult    -> L.build_fmul
  516.         | A.Div     -> L.build_fdiv
  517.         | A.Equal   -> L.build_fcmp L.Fcmp.Oeq
  518.         | A.Neq     -> L.build_fcmp L.Fcmp.One
  519.         | A.Less    -> L.build_fcmp L.Fcmp.Olt
  520.         | A.Leq     -> L.build_fcmp L.Fcmp.Ole
  521.         | A.Greater -> L.build_fcmp L.Fcmp.Ogt
  522.         | A.Geq     -> L.build_fcmp L.Fcmp.Oge
  523.         | A.And | A.Or | A.Mod ->
  524.             raise (Failure "internal error: semant should have rejected and/or on float")
  525.         ) e1' e2' "tmp" builder
  526.        (* TODO: list equality check *)
  527.        (* | SBinop ((A.List, _) as e1, op, e2) ->
  528.         let e1' = expr builder e1
  529.         and e2' = expr builder e2 in
  530.         (match op with
  531.           A.Equal   ->
  532.         | A.Neq     ->
  533.         | _ -> raise (Failure "internal error: semant should have rejected and/or on float")
  534.         ) e1' e2' "tmp" builder *)
  535.       | SBinop (e1, op, e2) ->
  536.         let e1' = expr builder e1
  537.         and e2' = expr builder e2 in
  538.         (match op with
  539.           A.Add     -> L.build_add
  540.         | A.Sub     -> L.build_sub
  541.         | A.Mult    -> L.build_mul
  542.         | A.Div     -> L.build_sdiv
  543.         | A.Mod     -> L.build_srem
  544.         | A.And     -> L.build_and
  545.         | A.Or      -> L.build_or
  546.         | A.Equal   -> L.build_icmp L.Icmp.Eq
  547.         | A.Neq     -> L.build_icmp L.Icmp.Ne
  548.         | A.Less    -> L.build_icmp L.Icmp.Slt
  549.         | A.Leq     -> L.build_icmp L.Icmp.Sle
  550.         | A.Greater -> L.build_icmp L.Icmp.Sgt
  551.         | A.Geq     -> L.build_icmp L.Icmp.Sge
  552.         ) e1' e2' "tmp" builder
  553.     | SUnop(op, ((t, e'') as e)) ->
  554.           let e' = expr builder e in
  555.       (match op with
  556.         A.Neg when t = A.Float -> L.build_fneg e' "tmp" builder
  557.       | A.Neg                  -> L.build_neg e' "tmp" builder
  558.       | A.Not                  -> L.build_not e' "tmp" builder
  559.       | A.PlusPlusPre ->
  560.         let new_val = (L.build_add e' (L.const_int i32_t 1)) "tmp" builder in
  561.         let id = match (e'') with
  562.           SId s -> s
  563.           | _ -> raise (Failure ("++ operand must be an ID")) in
  564.         let var_ptr = (lookup id) in
  565.         let _ = L.build_store new_val var_ptr builder in new_val
  566.       | A.MinusMinusPre ->
  567.         let new_val = (L.build_sub e' (L.const_int i32_t 1)) "tmp" builder in
  568.         let id = match (e'') with
  569.           SId s -> s
  570.           | _ -> raise (Failure ("-- operand must be an ID")) in
  571.         let var_ptr = (lookup id) in
  572.         let _ = L.build_store new_val var_ptr builder in new_val
  573.       | A.PlusPlusPost ->
  574.         let new_val = (L.build_add e' (L.const_int i32_t 1)) "tmp" builder in
  575.         let id = match (e'') with
  576.           SId s -> s
  577.           | _ -> raise (Failure ("++ operand must be an ID")) in
  578.         let var_ptr = (lookup id) in
  579.         let _ = L.build_store new_val var_ptr builder in e'
  580.       | A.MinusMinusPost ->
  581.         let new_val = (L.build_sub e' (L.const_int i32_t 1)) "tmp" builder in
  582.         let id = match (e'') with
  583.           SId s -> s
  584.           | _ -> raise (Failure ("-- operand must be an ID")) in
  585.         let var_ptr = (lookup id) in
  586.         let _ = L.build_store new_val var_ptr builder in e')
  587.  
  588.     | SListGet (list_type, id, e) ->
  589.       L.build_call (StringMap.find (type_str list_type) list_get) [| (lookup id); (expr builder e) |] "list_get" builder
  590.     | SListSize (list_type, id) ->
  591.       L.build_call ((StringMap.find (type_str list_type)) list_size) [| (lookup id) |] "list_size" builder
  592.     | SListPop (list_type, id) ->
  593.       L.build_call ((StringMap.find (type_str list_type)) list_pop) [| (lookup id) |] "list_pop" builder
  594.     | SListSlice (list_type, id, e1, e2) ->
  595.        let ltype = (ltype_of_typ list_type) in
  596.        let new_list_ptr = L.build_alloca (list_t ltype) "new_list_ptr" builder in
  597.        let _ = init_list builder new_list_ptr list_type in
  598.        let e' = match (fst e1, fst e2) with
  599.            (A.Int, A.Int) -> (expr builder e1, expr builder e2)
  600.           | (A.Void, A.Int) -> (L.const_int i32_t 0, expr builder e2)
  601.           | (A.Int, A.Void) ->  (expr builder e1, L.build_sub (expr builder (A.Int, SListSize(list_type, id))) (L.const_int i32_t 1) "size_min_one" builder)
  602.           | (A.Void, A.Void) -> (L.const_int i32_t 0, L.build_sub (expr builder (A.Int, SListSize(list_type, id))) (L.const_int i32_t 1) "size_min_one" builder)
  603.           | _ -> raise (Failure ("illegal list slice arguments"))
  604.        in
  605.        let _ = L.build_call ((StringMap.find (type_str list_type)) list_slice) [| (lookup id); new_list_ptr; fst e'; snd e' |] "" builder in
  606.        L.build_load new_list_ptr "new_list" builder
  607.     | SListFind (list_type, id, e) ->
  608.       L.build_call (StringMap.find (type_str list_type) list_find) [| (lookup id); (expr builder e) |] "list_find" builder
  609.     | SListLiteral (list_type, literals) ->
  610.        let ltype = (ltype_of_typ list_type) in
  611.        let new_list_ptr = L.build_alloca (list_t ltype) "new_list_ptr" builder in
  612.        let _ = init_list builder new_list_ptr list_type in
  613.        let map_func literal =
  614.           ignore(L.build_call (StringMap.find (type_str list_type) list_push) [| new_list_ptr; (expr builder literal) |] "" builder);
  615.        in
  616.        let _ = List.rev (List.map map_func literals) in
  617.        L.build_load new_list_ptr "new_list" builder
  618.     | SCall ("prints", [e]) ->
  619.       L.build_call printf_func [| str_format_str ; (expr builder e) |] "printf" builder
  620.     | SCall ("printi", [e]) ->
  621.       L.build_call printf_func [| int_format_str ; (expr builder e) |] "printf" builder
  622.     | SCall ("printb", [e]) ->
  623.       L.build_call printf_func [| int_format_str; (expr builder e) |] "printf" builder
  624.     | SCall ("printf", [e]) ->
  625.       L.build_call printf_func [| float_format_str ; (expr builder e) |] "printf" builder
  626.     | SCall (f, args) ->
  627.          let (fdef, fdecl) = StringMap.find f function_decls in
  628.          let llargs = List.rev (List.map (expr builder) (List.rev args)) in
  629.          let result = (match fdecl.styp with
  630.                               A.Void -> ""
  631.                             | _ -> f ^ "_result") in
  632.                L.build_call fdef (Array.of_list llargs) result builder
  633.          in
  634.  
  635.     (* Build the code for the given statement; return the builder for
  636.        the statement's successor (i.e., the next instruction will be built
  637.        after the one generated by this call) *)
  638.  
  639.     let rec stmt builder = function
  640.         SBlock sl -> List.fold_left stmt builder sl
  641.       | SListPush (id, e) ->
  642.           ignore(L.build_call (StringMap.find (type_str (fst e)) list_push) [| (lookup id); (expr builder e) |] "" builder); builder
  643.       | SListSet (list_type, id, e1, e2) ->
  644.           ignore(L.build_call (StringMap.find (type_str list_type) list_set) [| (lookup id); (expr builder e1); (expr builder e2) |] "" builder); builder
  645.       | SListClear (list_type, id) ->
  646.           ignore(init_list builder (lookup id) list_type); builder
  647.       | SListRemove (id, e) ->
  648.           ignore(L.build_call (StringMap.find (type_str (fst e)) list_remove) [| (lookup id); (expr builder e) |] "" builder); builder
  649.       | SListInsert (id, e1, e2) ->
  650.           ignore(L.build_call (StringMap.find (type_str (fst e2)) list_insert) [| (lookup id); (expr builder e1); (expr builder e2) |] "" builder); builder
  651.       | SListReverse (list_type, id) ->
  652.           ignore(L.build_call (StringMap.find (type_str list_type) list_reverse) [| (lookup id) |] "" builder); builder
  653.       | SExpr e -> ignore(expr builder e); builder
  654.       | SReturn e -> ignore(match fdecl.styp with
  655.                               (* Special "return nothing" instr *)
  656.                               A.Void -> L.build_ret_void builder
  657.                               (* Build return statement *)
  658.                             | _ -> L.build_ret (expr builder e) builder );
  659.                      builder
  660.       | SIf (predicate, then_stmt, else_stmt) ->
  661.          let bool_val = expr builder predicate in
  662.          let merge_bb = L.append_block context "merge" the_function in
  663.          let build_br_merge = L.build_br merge_bb in (* partial function *)
  664.  
  665.          let then_bb = L.append_block context "then" the_function in
  666.          add_terminal (stmt (L.builder_at_end context then_bb) then_stmt)
  667.          build_br_merge;
  668.  
  669.          let else_bb = L.append_block context "else" the_function in
  670.          add_terminal (stmt (L.builder_at_end context else_bb) else_stmt)
  671.          build_br_merge;
  672.  
  673.          ignore(L.build_cond_br bool_val then_bb else_bb builder);
  674.          L.builder_at_end context merge_bb
  675.  
  676.       | SWhile (predicate, body) ->
  677.         let pred_bb = L.append_block context "while" the_function in
  678.         ignore(L.build_br pred_bb builder);
  679.  
  680.         let body_bb = L.append_block context "while_body" the_function in
  681.         add_terminal (stmt (L.builder_at_end context body_bb) body)
  682.           (L.build_br pred_bb);
  683.  
  684.         let pred_builder = L.builder_at_end context pred_bb in
  685.         let bool_val = expr pred_builder predicate in
  686.  
  687.         let merge_bb = L.append_block context "merge" the_function in
  688.         ignore(L.build_cond_br bool_val body_bb merge_bb pred_builder);
  689.         L.builder_at_end context merge_bb
  690.  
  691.       (* Implement for loops as while loops *)
  692.       | SFor (e1, e2, e3, body) -> stmt builder
  693.         ( SBlock [SExpr e1 ; SWhile (e2, SBlock [body ; SExpr e3]) ] )
  694.      
  695.       in
  696.  
  697.     (* Build the code for each statement in the function *)
  698.     let builder = stmt builder (SBlock fdecl.sbody) in
  699.  
  700.     (* Add a return if the last block falls off the end *)
  701.     add_terminal builder (match fdecl.styp with
  702.         A.Void -> L.build_ret_void
  703.       | A.Float -> L.build_ret (L.const_float float_t 0.0)
  704.       | t -> L.build_ret (L.const_int (ltype_of_typ t) 0))
  705.   in
  706.  
  707.   List.iter build_function_body functions;
  708.   the_module
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement