def make_branch_func_object() -> Tuple[Function, Tuple[BasicBlock, ...]]: bb0 = BasicBlock("bb0") bb1 = BasicBlock("bb1") bb2 = BasicBlock("bb2") bb3 = BasicBlock("bb3") bb0.add_inst(bytecode.CopyInst(Var('v0'), NumLit(SNum(42)))) bb0.add_inst(bytecode.BrInst(Var('x'), bb1)) bb0.add_inst(bytecode.JmpInst(bb2)) bb1.add_inst( bytecode.BinopInst(Var('v0'), Binop.ADD, Var('v0'), NumLit(SNum(27)))) bb1.add_inst(bytecode.JmpInst(bb3)) bb2.add_inst(bytecode.CopyInst(Var('v0'), SymLit(SSym('hi')))) bb2.add_inst(bytecode.JmpInst(bb3)) bb3.add_inst(bytecode.ReturnInst(Var('v0'))) return Function([Var('x')], bb0), (bb0, bb1, bb2, bb3)
def make_func() -> Function: bb0 = BasicBlock("bb0") bb1 = BasicBlock("bb1") bb0.add_inst(bytecode.CopyInst(Var('v0'), NumLit(SNum(42)))) bb0.add_inst( bytecode.BinopInst(Var('v1'), Binop.ADD, Var('v0'), NumLit(SNum(69)))) bb0.add_inst(bytecode.JmpInst(bb1)) bb1.add_inst(bytecode.ReturnInst(Var('v1'))) return Function([], bb0)
def visit_SCall(self, call: sexp.SCall) -> None: assert not self.quoted, 'Non-primitives in quoted list unsupported' if self._is_true_assertion(call): self.result = bytecode.NumLit(sexp.SNum(0)) return tail_call_data = self._get_tail_call_data(call) is_known_function = self._is_known_function(call) arity_known_correct = self._arity_known_correct( call, is_known_function, tail_call_data) tail_call_args_compatible = self._tail_call_args_compatible( call, tail_call_data) func_to_call = self._get_func_to_call( call, is_known_function, arity_known_correct, tail_call_data, tail_call_args_compatible) args = self._emit_args(call) if tail_call_data is not None and func_to_call is None: for arg, param in zip(args, tail_call_data.func_params): local_var = self.local_env[param] if arg != local_var: self.end_block.add_inst(bytecode.CopyInst(local_var, arg)) assert self._function_entrypoint is not None self.end_block.add_inst( bytecode.JmpInst(self._function_entrypoint)) # We need a placeholder result since we're jumping back # to the beginning of the function self.result = bytecode.NumLit(sexp.SNum(0)) else: assert func_to_call is not None call_result_var = bytecode.Var(next(self.var_names)) call_instr = bytecode.CallInst( call_result_var, func_to_call, args, specialization=self._get_arg_types(call)) self.end_block.add_inst(call_instr) self.result = call_result_var
def visit_SConditional(self, conditional: sexp.SConditional) -> None: assert not self.quoted, 'Non-primitives in quoted list unsupported' if (self._expr_types is not None and self._expr_types.expr_value_known(conditional.test)): test_val = self._expr_types.get_expr_value(conditional.test) assert isinstance(test_val, sexp.SBool) branch_to_emit = (conditional.then_expr if test_val.value else conditional.else_expr) emitter = ExpressionEmitter( self.parent_block, self.bb_names, self.var_names, self.local_env, self.global_env, function_entrypoint=self._function_entrypoint, tail_calls=self._tail_calls, expr_types=self._expr_types) emitter.visit(branch_to_emit) self.result = emitter.result self.end_block = emitter.end_block return test_emitter = ExpressionEmitter( self.parent_block, self.bb_names, self.var_names, self.local_env, self.global_env, function_entrypoint=self._function_entrypoint, tail_calls=self._tail_calls, expr_types=self._expr_types) test_emitter.visit(conditional.test) then_block = bytecode.BasicBlock(next(self.bb_names)) else_block = bytecode.BasicBlock(next(self.bb_names)) result_var = bytecode.Var(next(self.var_names)) then_br_instr = bytecode.BrInst(test_emitter.result, then_block) else_br_instr = bytecode.JmpInst(else_block) test_emitter.end_block.add_inst(then_br_instr) test_emitter.end_block.add_inst(else_br_instr) then_emitter = ExpressionEmitter( then_block, self.bb_names, self.var_names, self.local_env, self.global_env, function_entrypoint=self._function_entrypoint, tail_calls=self._tail_calls, expr_types=self._expr_types) then_emitter.visit(conditional.then_expr) then_result_instr = bytecode.CopyInst(result_var, then_emitter.result) then_emitter.end_block.add_inst(then_result_instr) else_emitter = ExpressionEmitter( else_block, self.bb_names, self.var_names, self.local_env, self.global_env, function_entrypoint=self._function_entrypoint, tail_calls=self._tail_calls, expr_types=self._expr_types) else_emitter.visit(conditional.else_expr) else_result_instr = bytecode.CopyInst(result_var, else_emitter.result) else_emitter.end_block.add_inst(else_result_instr) new_end_block = bytecode.BasicBlock(next(self.bb_names)) then_emitter.end_block.add_inst(bytecode.JmpInst(new_end_block)) else_emitter.end_block.add_inst(bytecode.JmpInst(new_end_block)) self.end_block = new_end_block self.result = result_var