Ejemplo n.º 1
0
def generate_arg_check(name: str, typ: RType, emitter: Emitter,
                       error_code: str, optional: bool = False) -> None:
    """Insert a runtime check for argument and unbox if necessary.

    The object is named PyObject *obj_{}. This is expected to generate
    a value of name arg_{} (unboxed if necessary). For each primitive a runtime
    check ensures the correct type.
    """
    if typ.is_unboxed:
        # Borrow when unboxing to avoid reference count manipulation.
        emitter.emit_unbox('obj_{}'.format(name), 'arg_{}'.format(name), typ,
                           error_code, declare_dest=True, borrow=True, optional=optional)
    elif is_object_rprimitive(typ):
        # Object is trivial since any object is valid
        if optional:
            emitter.emit_line('PyObject *arg_{};'.format(name))
            emitter.emit_line('if (obj_{} == NULL) {{'.format(name))
            emitter.emit_line('arg_{} = {};'.format(name, emitter.c_error_value(typ)))
            emitter.emit_lines('} else {', 'arg_{} = obj_{}; '.format(name, name), '}')
        else:
            emitter.emit_line('PyObject *arg_{} = obj_{};'.format(name, name))
    else:
        emitter.emit_cast('obj_{}'.format(name), 'arg_{}'.format(name), typ,
                          declare_dest=True, optional=optional)
        if optional:
            emitter.emit_line('if (obj_{} != NULL && arg_{} == NULL) {}'.format(
                              name, name, error_code))
        else:
            emitter.emit_line('if (arg_{} == NULL) {}'.format(name, error_code))
Ejemplo n.º 2
0
def generate_native_function(fn: FuncIR,
                             emitter: Emitter,
                             source_path: str,
                             module_name: str,
                             optimize_int: bool = True) -> None:
    if optimize_int:
        const_int_regs = find_constant_integer_registers(fn.blocks)
    else:
        const_int_regs = {}
    declarations = Emitter(emitter.context, fn.env)
    names = generate_names_for_env(fn.env)
    body = Emitter(emitter.context, fn.env, names)
    visitor = FunctionEmitterVisitor(body, declarations, source_path, module_name, const_int_regs)

    declarations.emit_line('{} {{'.format(native_function_header(fn.decl, 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)
        init = ''
        if r in fn.env.vars_needing_init:
            init = ' = {}'.format(declarations.c_error_value(r.type))
        if r not in const_int_regs:
            declarations.emit_line('{ctype}{prefix}{name}{init};'.format(ctype=ctype,
                                                                         prefix=REG_PREFIX,
                                                                         name=names[r],
                                                                         init=init))

    # 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)