def rewrite_obj_return(func, env): """ Handle returning stack-allocated objects. """ if should_skip(env): return context = env['flypy.typing.context'] restype = env['flypy.typing.restype'] envs = env['flypy.state.envs'] builder = Builder(func) stack_alloc = representation.byref(restype) if stack_alloc: out = func.add_arg(func.temp("out"), opaque_t) context[out] = Pointer[restype] func.type = types.Function(types.Void, func.type.argtypes, False) for arg in func.args: arg.type = opaque_t func.type = types.Function(func.type.restype, (opaque_t, ) * len(func.args), False) is_generator = env['flypy.state.generator'] for op in func.ops: if (op.opcode == 'ret' and op.args[0] is not None and stack_alloc and not is_generator): # ret val => # store (load val) out ; ret void [val] = op.args builder.position_before(op) newval = builder.load(val) builder.store(newval, out) op.set_args([None]) # Update context context[newval] = StackVar[context[val]] elif op.opcode == 'call' and op.type != types.Void: # result = call(f, ...) => # alloca result ; call(f, ..., &result) ty = context[op] if conversion.byref(ty): f, args = op.args if not is_flypy_cc(f) or should_skip(envs[f]): continue builder.position_before(op) retval = builder.alloca(opaque_t) builder.position_after(op) op.replace_uses(retval) newargs = args + [retval] op.set_args([f, newargs]) # Update context context[retval] = context[op] context[op] = void
def rewrite_obj_return(func, env): """ Handle returning stack-allocated objects. """ if should_skip(env): return context = env['flypy.typing.context'] restype = env['flypy.typing.restype'] envs = env['flypy.state.envs'] builder = Builder(func) stack_alloc = representation.byref(restype) if stack_alloc: out = func.add_arg(func.temp("out"), opaque_t) context[out] = Pointer[restype] func.type = types.Function(types.Void, func.type.argtypes, False) for arg in func.args: arg.type = opaque_t func.type = types.Function(func.type.restype, (opaque_t,) * len(func.args), False) is_generator = env['flypy.state.generator'] for op in func.ops: if (op.opcode == 'ret' and op.args[0] is not None and stack_alloc and not is_generator): # ret val => # store (load val) out ; ret void [val] = op.args builder.position_before(op) newval = builder.load(val) builder.store(newval, out) op.set_args([None]) # Update context context[newval] = StackVar[context[val]] elif op.opcode == 'call' and op.type != types.Void: # result = call(f, ...) => # alloca result ; call(f, ..., &result) ty = context[op] if conversion.byref(ty): f, args = op.args if not is_flypy_cc(f) or should_skip(envs[f]): continue builder.position_before(op) retval = builder.alloca(opaque_t) builder.position_after(op) op.replace_uses(retval) newargs = args + [retval] op.set_args([f, newargs]) # Update context context[retval] = context[op] context[op] = void
def lltyping(func, env): """Annotate the function with the low-level representation types""" if not env['flypy.state.opaque']: context = env['flypy.typing.context'] resolve = partial(resolve_type, context) for arg in func.args: resolve(arg) for op in func.ops: if op.opcode == 'exc_catch': continue op.replace(resolve(op)) op.set_args(nestedmap(resolve, op.args)) restype = env['flypy.typing.restype'] if conversion.byref(restype): ll_restype = ptypes.Void else: ll_restype = compiler.representation_type(restype) func.type = ptypes.Function(ll_restype, [arg.type for arg in func.args], False)