def build_or_get_function(self, parent, volpe_args): module: ir.Module = parent.builder.module func_args = unwrap(self.args()) if not isinstance(volpe_args, VolpeObject): func_args = ir.LiteralStructType([func_args]) for func in module.functions: if func.name == self.name: break else: func_type = ir.FunctionType(unwrap(self.ret()), func_args) func = ir.Function(module, func_type, self.name) volpe_func_type = ir.FunctionType(unwrap( self.ret()), [ir.LiteralStructType([]), unwrap(self.args())]) volpe_func = ir.Function(module, volpe_func_type, str(next(module.func_count))) with build_func(volpe_func) as (b, args): b: ir.IRBuilder args = [args[1]] if isinstance(volpe_args, VolpeObject): args = [ b.extract_value(args[0], i) for i in range(len(volpe_args.type_dict)) ] b.ret(b.call(func, args)) return volpe_func
def build_or_get_function(self, parent, args): inst = self.tree.instances[args] if not hasattr(inst, "func"): arg_type = inst.children[0].return_type ret_type = inst.children[1].return_type module = parent.builder.module func_name = str(next(module.func_count)) func_type = ir.FunctionType( unwrap(ret_type), [unwrap(self), unwrap(arg_type)]) inst.func = ir.Function(module, func_type, func_name) with build_func(inst.func) as (b, args): b: ir.IRBuilder with options(b, args[1].type) as (rec, phi): rec(args[1]) new_values = [ b.extract_value(args[0], i) for i in range(len(self.env)) ] env_scope = dict(zip(self.env.keys(), new_values)) env_scope["@"] = args[0] def scope(name): return env_scope[name] parent.__class__(b, inst.children[1], scope, b.ret, rec, (inst.children[0], phi)) return inst.func
def build_main(module, run_func, printf_func): main_func = ir.Function( module, ir.FunctionType(int32, [int32, char.as_pointer().as_pointer()]), "main") with build_func(main_func) as (b, args): num_args = b.zext(args[0], int64) closure = b.call(run_func, []) func = b.extract_value(closure, 0) env_ptr = b.extract_value(closure, 3) pointer = b.call(module.malloc, [b.mul(num_args, size(string_type))]) pointer = b.bitcast(pointer, string_type.unwrap().as_pointer()) with options(b, int64) as (ret, phi): ret(int64(0)) with b.if_then(b.icmp_unsigned("<", phi, num_args)): string = b.load(b.gep(args[1], [phi])) new_string = string_to_volpe(b, string) b.store(new_string, b.gep(pointer, [phi])) ret(b.add(phi, int64(1))) arguments = string_array.unwrap()(ir.Undefined) arguments = b.insert_value(arguments, pointer, 0) arguments = b.insert_value(arguments, num_args, 1) arg_obj = string_obj.unwrap()(ir.Undefined) arg_obj = b.insert_value(arg_obj, arguments, 0) res = b.call(func, [env_ptr, arg_obj]) free(b, closure) print_obj = VolpeObject({"_0": string_type}).unwrap()(ir.Undefined) print_obj = b.insert_value(print_obj, res, 0) b.call(b.extract_value(printf_func, 0), [pint8(ir.Undefined), print_obj]) b.ret(int32(0))
def volpe_llvm(tree: TypeTree, verbose=False, more_verbose=False, console=False): if more_verbose: print(tree.pretty()) arg_scope = {} def scope(name, local_tree: TypeTree): if name in arg_scope: return arg_scope[name] raise VolpeError(f"variable `{name}` not found", local_tree) AnnotateScope(tree, scope) if verbose: print(tree.pretty()) module = ir.Module("program") module.func_count = itertools.count() run_func = ir.Function( module, ir.FunctionType(unknown, [unwrap(tree.return_type).as_pointer()]), "run") with build_func(run_func) as (b, args): arg_scope = {} def scope(name): return arg_scope[name] def ret(value): b.store(value, args[0], 8) b.ret_void() LLVMScope(b, tree, scope, ret, None) return str(module)