Exemplo n.º 1
0
def generate_native_function(fn: FuncIR, emitter: Emitter, source_path: str,
                             module_name: str) -> None:
    declarations = Emitter(emitter.context, fn.env)
    body = Emitter(emitter.context, fn.env)
    visitor = FunctionEmitterVisitor(body, declarations, fn.name, source_path,
                                     module_name)

    declarations.emit_line('{} {{'.format(native_function_header(fn, emitter)))
    body.indent()

    for r, i in fn.env.indexes.items():
        if isinstance(r.type, RTuple):
            emitter.declare_tuple_struct(r.type)
        if i < len(fn.args):
            continue  # skip the arguments
        ctype = emitter.ctype_spaced(r.type)
        declarations.emit_line('{ctype}{prefix}{name};'.format(
            ctype=ctype, prefix=REG_PREFIX, name=r.name))

    # Before we emit the blocks, give them all labels
    for i, block in enumerate(fn.blocks):
        block.label = i

    for block in fn.blocks:
        body.emit_label(block)
        for op in block.ops:
            op.accept(visitor)

    body.emit_line('}')

    emitter.emit_from_emitter(declarations)
    emitter.emit_from_emitter(body)
Exemplo n.º 2
0
def generate_wrapper_core(fn: FuncIR,
                          emitter: Emitter,
                          optional_args: Optional[List[RuntimeArg]] = None,
                          arg_names: Optional[List[str]] = None,
                          cleanups: Optional[List[str]] = None,
                          traceback_code: Optional[str] = None) -> None:
    """Generates the core part of a wrapper function for a native function.
    This expects each argument as a PyObject * named obj_{arg} as a precondition.
    It converts the PyObject *s to the necessary types, checking and unboxing if necessary,
    makes the call, then boxes the result if necessary and returns it.
    """

    optional_args = optional_args or []
    cleanups = cleanups or []
    use_goto = bool(cleanups or traceback_code)
    error_code = 'return NULL;' if not use_goto else 'goto fail;'

    arg_names = arg_names or [arg.name for arg in fn.args]
    for arg_name, arg in zip(arg_names, fn.args):
        # Suppress the argument check for *args/**kwargs, since we know it must be right.
        typ = arg.type if arg.kind not in (ARG_STAR,
                                           ARG_STAR2) else object_rprimitive
        generate_arg_check(arg_name, typ, emitter, error_code, arg
                           in optional_args)
    native_args = ', '.join('arg_{}'.format(arg) for arg in arg_names)
    if fn.ret_type.is_unboxed or use_goto:
        # TODO: The Py_RETURN macros return the correct PyObject * with reference count handling.
        #       Are they relevant?
        emitter.emit_line('{}retval = {}{}({});'.format(
            emitter.ctype_spaced(fn.ret_type), NATIVE_PREFIX,
            fn.cname(emitter.names), native_args))
        emitter.emit_lines(*cleanups)
        if fn.ret_type.is_unboxed:
            emitter.emit_error_check('retval', fn.ret_type, 'return NULL;')
            emitter.emit_box('retval',
                             'retbox',
                             fn.ret_type,
                             declare_dest=True)

        emitter.emit_line('return {};'.format(
            'retbox' if fn.ret_type.is_unboxed else 'retval'))
    else:
        emitter.emit_line('return {}{}({});'.format(NATIVE_PREFIX,
                                                    fn.cname(emitter.names),
                                                    native_args))
        # TODO: Tracebacks?

    if use_goto:
        emitter.emit_label('fail')
        emitter.emit_lines(*cleanups)
        if traceback_code:
            emitter.emit_lines(traceback_code)
        emitter.emit_lines('return NULL;')
Exemplo n.º 3
0
def generate_native_function(fn: FuncIR, emitter: Emitter) -> None:
    declarations = Emitter(emitter.context, fn.env)
    body = Emitter(emitter.context, fn.env)
    visitor = FunctionEmitterVisitor(body, declarations)

    declarations.emit_line('{} {{'.format(native_function_header(fn)))
    body.indent()

    for i in range(len(fn.args), fn.env.num_regs()):
        ctype = fn.env.types[i].ctype
        declarations.emit_line('{ctype} {prefix}{name};'.format(
            ctype=ctype, prefix=REG_PREFIX, name=fn.env.names[i]))

    for block in fn.blocks:
        body.emit_label(block.label)
        for op in block.ops:
            op.accept(visitor)

    body.emit_line('}')

    emitter.emit_from_emitter(declarations)
    emitter.emit_from_emitter(body)