1cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar(*===----------------------------------------------------------------------=== 2cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * Code Generation 3cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar *===----------------------------------------------------------------------===*) 4cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 5cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaaropen Llvm 6cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 7cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaarexception Error of string 8cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 9cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaarlet context = global_context () 10cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaarlet the_module = create_module context "my cool jit" 11cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaarlet builder = builder context 12cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaarlet named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 13cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaarlet double_type = double_type context 14cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 15cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaarlet rec codegen_expr = function 16cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Ast.Number n -> const_float double_type n 17cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Ast.Variable name -> 18cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (try Hashtbl.find named_values name with 19cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Not_found -> raise (Error "unknown variable name")) 20cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Ast.Binary (op, lhs, rhs) -> 21cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let lhs_val = codegen_expr lhs in 22cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let rhs_val = codegen_expr rhs in 23cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar begin 24cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar match op with 2588364df7b6429fa96bb5130ea73bd40b0629e30eEric Christopher | '+' -> build_fadd lhs_val rhs_val "addtmp" builder 2688364df7b6429fa96bb5130ea73bd40b0629e30eEric Christopher | '-' -> build_fsub lhs_val rhs_val "subtmp" builder 2788364df7b6429fa96bb5130ea73bd40b0629e30eEric Christopher | '*' -> build_fmul lhs_val rhs_val "multmp" builder 28cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | '<' -> 29cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Convert bool 0/1 to double 0.0 or 1.0 *) 30cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in 31cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar build_uitofp i double_type "booltmp" builder 32cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | _ -> raise (Error "invalid binary operator") 33cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar end 34cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Ast.Call (callee, args) -> 35cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Look up the name in the module table. *) 36cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let callee = 37cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar match lookup_function callee the_module with 38cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Some callee -> callee 39cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | None -> raise (Error "unknown function referenced") 40cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar in 41cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let params = params callee in 42cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 43cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* If argument mismatch error. *) 44cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar if Array.length params == Array.length args then () else 45cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar raise (Error "incorrect # arguments passed"); 46cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let args = Array.map codegen_expr args in 47cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar build_call callee args "calltmp" builder 48cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Ast.If (cond, then_, else_) -> 49cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let cond = codegen_expr cond in 50cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 51cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Convert condition to a bool by comparing equal to 0.0 *) 52cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let zero = const_float double_type 0.0 in 53cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in 54cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 55cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Grab the first block so that we might later add the conditional branch 56cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * to it at the end of the function. *) 57cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let start_bb = insertion_block builder in 58cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let the_function = block_parent start_bb in 59cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 60cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let then_bb = append_block context "then" the_function in 61cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 62cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Emit 'then' value. *) 63cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar position_at_end then_bb builder; 64cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let then_val = codegen_expr then_ in 65cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 66cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Codegen of 'then' can change the current block, update then_bb for the 67cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * phi. We create a new name because one is used for the phi node, and the 68cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * other is used for the conditional branch. *) 69cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let new_then_bb = insertion_block builder in 70cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 71cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Emit 'else' value. *) 72cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let else_bb = append_block context "else" the_function in 73cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar position_at_end else_bb builder; 74cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let else_val = codegen_expr else_ in 75cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 76cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Codegen of 'else' can change the current block, update else_bb for the 77cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * phi. *) 78cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let new_else_bb = insertion_block builder in 79cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 80cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Emit merge block. *) 81cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let merge_bb = append_block context "ifcont" the_function in 82cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar position_at_end merge_bb builder; 83cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in 84cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let phi = build_phi incoming "iftmp" builder in 85cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 86cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Return to the start block to add the conditional branch. *) 87cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar position_at_end start_bb builder; 88cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar ignore (build_cond_br cond_val then_bb else_bb builder); 89cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 90cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Set a unconditional branch at the end of the 'then' block and the 91cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * 'else' block to the 'merge' block. *) 92cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar position_at_end new_then_bb builder; ignore (build_br merge_bb builder); 93cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar position_at_end new_else_bb builder; ignore (build_br merge_bb builder); 94cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 95cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Finally, set the builder to the end of the merge block. *) 96cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar position_at_end merge_bb builder; 97cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 98cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar phi 99cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Ast.For (var_name, start, end_, step, body) -> 100cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Emit the start code first, without 'variable' in scope. *) 101cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let start_val = codegen_expr start in 102cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 103cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Make the new basic block for the loop header, inserting after current 104cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * block. *) 105cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let preheader_bb = insertion_block builder in 106cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let the_function = block_parent preheader_bb in 107cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let loop_bb = append_block context "loop" the_function in 108cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 109cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Insert an explicit fall through from the current block to the 110cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * loop_bb. *) 111cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar ignore (build_br loop_bb builder); 112cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 113cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Start insertion in loop_bb. *) 114cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar position_at_end loop_bb builder; 115cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 116cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Start the PHI node with an entry for start. *) 117cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let variable = build_phi [(start_val, preheader_bb)] var_name builder in 118cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 119cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Within the loop, the variable is defined equal to the PHI node. If it 120cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * shadows an existing variable, we have to restore it, so save it 121cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * now. *) 122cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let old_val = 123cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar try Some (Hashtbl.find named_values var_name) with Not_found -> None 124cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar in 125cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar Hashtbl.add named_values var_name variable; 126cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 127cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Emit the body of the loop. This, like any other expr, can change the 128cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * current BB. Note that we ignore the value computed by the body, but 129cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * don't allow an error *) 130cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar ignore (codegen_expr body); 131cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 132cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Emit the step value. *) 133cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let step_val = 134cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar match step with 135cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Some step -> codegen_expr step 136cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* If not specified, use 1.0. *) 137cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | None -> const_float double_type 1.0 138cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar in 139cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 140cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let next_var = build_add variable step_val "nextvar" builder in 141cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 142cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Compute the end condition. *) 143cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let end_cond = codegen_expr end_ in 144cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 145cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Convert condition to a bool by comparing equal to 0.0. *) 146cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let zero = const_float double_type 0.0 in 147cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in 148cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 149cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Create the "after loop" block and insert it. *) 150cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let loop_end_bb = insertion_block builder in 151cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let after_bb = append_block context "afterloop" the_function in 152cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 153cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Insert the conditional branch into the end of loop_end_bb. *) 154cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar ignore (build_cond_br end_cond loop_bb after_bb builder); 155cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 156cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Any new code will be inserted in after_bb. *) 157cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar position_at_end after_bb builder; 158cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 159cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Add a new entry to the PHI node for the backedge. *) 160cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar add_incoming (next_var, loop_end_bb) variable; 161cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 162cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Restore the unshadowed variable. *) 163cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar begin match old_val with 164cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Some old_val -> Hashtbl.add named_values var_name old_val 165cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | None -> () 166cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar end; 167cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 168cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* for expr always returns 0.0. *) 169cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar const_null double_type 170cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 171cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaarlet codegen_proto = function 172cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Ast.Prototype (name, args) -> 173cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Make the function type: double(double,double) etc. *) 174cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let doubles = Array.make (Array.length args) double_type in 175cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let ft = function_type double_type doubles in 176cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let f = 177cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar match lookup_function name the_module with 178cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | None -> declare_function name ft the_module 179cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 180cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* If 'f' conflicted, there was already something named 'name'. If it 181cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar * has a body, don't allow redefinition or reextern. *) 182cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Some f -> 183cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* If 'f' already has a body, reject this. *) 184cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar if block_begin f <> At_end f then 185cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar raise (Error "redefinition of function"); 186cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 187cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* If 'f' took a different number of arguments, reject. *) 188cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar if element_type (type_of f) <> ft then 189cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar raise (Error "redefinition of function with different # args"); 190cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar f 191cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar in 192cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 193cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Set names for all arguments. *) 194cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar Array.iteri (fun i a -> 195cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let n = args.(i) in 196cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar set_value_name n a; 197cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar Hashtbl.add named_values n a; 198cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar ) (params f); 199cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar f 200cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 201cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaarlet codegen_func the_fpm = function 202cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar | Ast.Function (proto, body) -> 203cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar Hashtbl.clear named_values; 204cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let the_function = codegen_proto proto in 205cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 206cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Create a new basic block to start insertion into. *) 207cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let bb = append_block context "entry" the_function in 208cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar position_at_end bb builder; 209cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 210cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar try 211cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let ret_val = codegen_expr body in 212cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 213cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Finish off the function. *) 214cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let _ = build_ret ret_val builder in 215cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 216cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Validate the generated code, checking for consistency. *) 217cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar Llvm_analysis.assert_valid_function the_function; 218cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 219cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar (* Optimize the function. *) 220cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar let _ = PassManager.run_function the_function the_fpm in 221cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar 222cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar the_function 223cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar with e -> 224cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar delete_function the_function; 225cabc7af293504ad256d2203ae88ee11cbc34c2edErick Tryzelaar raise e 226