Beispiel #1
0
 def test_register(self) -> None:
     op = LoadInt(5)
     self.block.ops.append(op)
     fn = FuncIR(
         FuncDecl('myfunc', None, 'mod',
                  FuncSignature([self.arg], list_rprimitive)), [self.reg],
         [self.block])
     value_names = generate_names_for_ir(fn.arg_regs, fn.blocks)
     emitter = Emitter(EmitterContext(NameGenerator([['mod']])),
                       value_names)
     generate_native_function(fn,
                              emitter,
                              'prog.py',
                              'prog',
                              optimize_int=False)
     result = emitter.fragments
     assert_string_arrays_equal([
         'PyObject *CPyDef_myfunc(CPyTagged cpy_r_arg) {\n',
         '    CPyTagged cpy_r_i0;\n',
         'CPyL0: ;\n',
         '    cpy_r_i0 = 10;\n',
         '}\n',
     ],
                                result,
                                msg='Generated code invalid')
Beispiel #2
0
def compile_ir_to_c(
    groups: Groups,
    modules: ModuleIRs,
    result: BuildResult,
    mapper: Mapper,
    compiler_options: CompilerOptions,
) -> Dict[Optional[str], List[Tuple[str, str]]]:
    """Compile a collection of ModuleIRs to C source text.

    Returns a dictionary mapping group names to a list of (file name,
    file text) pairs.
    """
    source_paths = {
        source.module: result.graph[source.module].xpath
        for sources, _ in groups for source in sources
    }

    names = NameGenerator([[source.module for source in sources]
                           for sources, _ in groups])

    # Generate C code for each compilation group. Each group will be
    # compiled into a separate extension module.
    ctext: Dict[Optional[str], List[Tuple[str, str]]] = {}
    for group_sources, group_name in groups:
        group_modules = [(source.module, modules[source.module])
                         for source in group_sources
                         if source.module in modules]
        if not group_modules:
            ctext[group_name] = []
            continue
        generator = GroupGenerator(group_modules, source_paths, group_name,
                                   mapper.group_map, names, compiler_options)
        ctext[group_name] = generator.generate_c_for_modules()

    return ctext
Beispiel #3
0
    def setUp(self) -> None:
        self.env = Environment()
        self.n = self.env.add_local(Var('n'), int_rprimitive)
        self.m = self.env.add_local(Var('m'), int_rprimitive)
        self.k = self.env.add_local(Var('k'), int_rprimitive)
        self.l = self.env.add_local(Var('l'), list_rprimitive)  # noqa
        self.ll = self.env.add_local(Var('ll'), list_rprimitive)
        self.o = self.env.add_local(Var('o'), object_rprimitive)
        self.o2 = self.env.add_local(Var('o2'), object_rprimitive)
        self.d = self.env.add_local(Var('d'), dict_rprimitive)
        self.b = self.env.add_local(Var('b'), bool_rprimitive)
        self.t = self.env.add_local(Var('t'),
                                    RTuple([int_rprimitive, bool_rprimitive]))
        self.tt = self.env.add_local(
            Var('tt'),
            RTuple(
                [RTuple([int_rprimitive, bool_rprimitive]), bool_rprimitive]))
        ir = ClassIR('A', 'mod')
        ir.attributes = OrderedDict([('x', bool_rprimitive),
                                     ('y', int_rprimitive)])
        compute_vtable(ir)
        ir.mro = [ir]
        self.r = self.env.add_local(Var('r'), RInstance(ir))

        self.context = EmitterContext(NameGenerator([['mod']]))
        self.emitter = Emitter(self.context, self.env)
        self.declarations = Emitter(self.context, self.env)
        self.visitor = FunctionEmitterVisitor(self.emitter, self.declarations,
                                              'prog.py', 'prog')
Beispiel #4
0
    def setUp(self) -> None:
        self.env = Environment()
        self.n = self.env.add_local(Var('n'), int_rprimitive)
        self.m = self.env.add_local(Var('m'), int_rprimitive)
        self.k = self.env.add_local(Var('k'), int_rprimitive)
        self.l = self.env.add_local(Var('l'), list_rprimitive)  # noqa
        self.ll = self.env.add_local(Var('ll'), list_rprimitive)
        self.o = self.env.add_local(Var('o'), object_rprimitive)
        self.o2 = self.env.add_local(Var('o2'), object_rprimitive)
        self.d = self.env.add_local(Var('d'), dict_rprimitive)
        self.b = self.env.add_local(Var('b'), bool_rprimitive)
        self.s1 = self.env.add_local(Var('s1'), short_int_rprimitive)
        self.s2 = self.env.add_local(Var('s2'), short_int_rprimitive)
        self.i32 = self.env.add_local(Var('i32'), int32_rprimitive)
        self.i32_1 = self.env.add_local(Var('i32_1'), int32_rprimitive)
        self.i64 = self.env.add_local(Var('i64'), int64_rprimitive)
        self.i64_1 = self.env.add_local(Var('i64_1'), int64_rprimitive)
        self.ptr = self.env.add_local(Var('ptr'), pointer_rprimitive)
        self.t = self.env.add_local(Var('t'),
                                    RTuple([int_rprimitive, bool_rprimitive]))
        self.tt = self.env.add_local(
            Var('tt'),
            RTuple(
                [RTuple([int_rprimitive, bool_rprimitive]), bool_rprimitive]))
        ir = ClassIR('A', 'mod')
        ir.attributes = OrderedDict([('x', bool_rprimitive),
                                     ('y', int_rprimitive)])
        compute_vtable(ir)
        ir.mro = [ir]
        self.r = self.env.add_local(Var('r'), RInstance(ir))

        self.context = EmitterContext(NameGenerator([['mod']]))
Beispiel #5
0
 def test_name_generator(self) -> None:
     g = NameGenerator(['foo', 'foo.zar'])
     assert g.private_name('foo', 'f') == 'foo___f'
     assert g.private_name('foo', 'C.x.y') == 'foo___C___x___y'
     assert g.private_name('foo', 'C.x.y') == 'foo___C___x___y'
     assert g.private_name('foo.zar', 'C.x.y') == 'zar___C___x___y'
     assert g.private_name('foo', 'C.x_y') == 'foo___C___x_y'
     assert g.private_name('foo', 'C_x_y') == 'foo___C_x_y'
     assert g.private_name('foo', 'C_x_y') == 'foo___C_x_y'
     assert g.private_name('foo', '___') == 'foo______3_'
Beispiel #6
0
    def __init__(self, module_names: List[str]) -> None:
        self.temp_counter = 0
        self.names = NameGenerator(module_names)

        # The map below is used for generating declarations and
        # definitions at the top of the C file. The main idea is that they can
        # be generated at any time during the emit phase.

        # A map of a C identifier to whatever the C identifier declares. Currently this is
        # used for declaring structs and the key corresponds to the name of the struct.
        # The declaration contains the body of the struct.
        self.declarations = OrderedDict()  # type: Dict[str, HeaderDeclaration]
Beispiel #7
0
 def test_simple(self) -> None:
     self.block.ops.append(Return(self.reg))
     fn = FuncIR(FuncDecl('myfunc', None, 'mod', FuncSignature([self.arg], int_rprimitive)),
                 [self.block], self.env)
     emitter = Emitter(EmitterContext(NameGenerator([['mod']])))
     generate_native_function(fn, emitter, 'prog.py', 'prog', optimize_int=False)
     result = emitter.fragments
     assert_string_arrays_equal(
         [
             'CPyTagged CPyDef_myfunc(CPyTagged cpy_r_arg) {\n',
             'CPyL0: ;\n',
             '    return cpy_r_arg;\n',
             '}\n',
         ],
         result, msg='Generated code invalid')
Beispiel #8
0
    def __init__(self, module_names: List[str]) -> None:
        self.temp_counter = 0
        self.names = NameGenerator(module_names)

        # The two maps below are used for generating declarations or
        # definitions at the top of the C file. The main idea is that they can
        # be generated at any time during the emit phase.

        # A map of a C identifier to whatever the C identifier declares. Currently this is
        # used for declaring structs and the key corresponds to the name of the struct.
        # The declaration contains the body of the struct.
        self.declarations = OrderedDict()  # type: Dict[str, HeaderDeclaration]

        # A map from C identifier to code that defined the C identifier. This
        # is similar to to 'declarations', but these may appear after the
        # declarations in the generated code.
        self.statics = OrderedDict()  # type: Dict[str, str]
Beispiel #9
0
 def test_register(self) -> None:
     self.env.temp_index = 0
     op = LoadInt(5)
     self.block.ops.append(op)
     self.env.add_op(op)
     fn = FuncIR(FuncDecl('myfunc', None, 'mod', FuncSignature([self.arg], list_rprimitive)),
                 [self.block], self.env)
     emitter = Emitter(EmitterContext(NameGenerator([['mod']])))
     generate_native_function(fn, emitter, 'prog.py', 'prog', False)
     result = emitter.fragments
     assert_string_arrays_equal(
         [
             'PyObject *CPyDef_myfunc(CPyTagged cpy_r_arg) {\n',
             '    CPyTagged cpy_r_i0;\n',
             'CPyL0: ;\n',
             '    cpy_r_i0 = 10;\n',
             '}\n',
         ],
         result, msg='Generated code invalid')
Beispiel #10
0
    def setUp(self) -> None:
        self.registers = []  # type: List[Register]

        def add_local(name: str, rtype: RType) -> Register:
            reg = Register(rtype, name)
            self.registers.append(reg)
            return reg

        self.n = add_local('n', int_rprimitive)
        self.m = add_local('m', int_rprimitive)
        self.k = add_local('k', int_rprimitive)
        self.l = add_local('l', list_rprimitive)  # noqa
        self.ll = add_local('ll', list_rprimitive)
        self.o = add_local('o', object_rprimitive)
        self.o2 = add_local('o2', object_rprimitive)
        self.d = add_local('d', dict_rprimitive)
        self.b = add_local('b', bool_rprimitive)
        self.s1 = add_local('s1', short_int_rprimitive)
        self.s2 = add_local('s2', short_int_rprimitive)
        self.i32 = add_local('i32', int32_rprimitive)
        self.i32_1 = add_local('i32_1', int32_rprimitive)
        self.i64 = add_local('i64', int64_rprimitive)
        self.i64_1 = add_local('i64_1', int64_rprimitive)
        self.ptr = add_local('ptr', pointer_rprimitive)
        self.t = add_local('t', RTuple([int_rprimitive, bool_rprimitive]))
        self.tt = add_local(
            'tt',
            RTuple(
                [RTuple([int_rprimitive, bool_rprimitive]), bool_rprimitive]))
        ir = ClassIR('A', 'mod')
        ir.attributes = OrderedDict([('x', bool_rprimitive),
                                     ('y', int_rprimitive)])
        compute_vtable(ir)
        ir.mro = [ir]
        self.r = add_local('r', RInstance(ir))

        self.context = EmitterContext(NameGenerator([['mod']]))
Beispiel #11
0
 def cname(self, names: NameGenerator) -> str:
     return names.private_name(self.module_name, self.shortname)
Beispiel #12
0
 def setUp(self) -> None:
     self.env = Environment()
     self.n = self.env.add_local(Var('n'), int_rprimitive)
     self.context = EmitterContext(NameGenerator([['mod']]))
     self.emitter = Emitter(self.context, self.env)
Beispiel #13
0
def setter_name(cl: ClassIR, attribute: str, names: NameGenerator) -> str:
    return names.private_name(cl.module_name, f'{cl.name}_set{attribute}')
Beispiel #14
0
def setter_name(cl: ClassIR, attribute: str, names: NameGenerator) -> str:
    return names.private_name(cl.module_name,
                              '{}_set{}'.format(cl.name, attribute))
Beispiel #15
0
 def name_prefix(self, names: NameGenerator) -> str:
     return names.private_name(self.module_name, self.name)
Beispiel #16
0
 def cname(self, names: NameGenerator) -> str:
     partial_name = short_id_from_name(self.name, self.shortname, self._line)
     return names.private_name(self.module_name, partial_name)
Beispiel #17
0
def compile_modules_to_c(
    result: BuildResult,
    compiler_options: CompilerOptions,
    errors: Errors,
    groups: Groups,
) -> Tuple[ModuleIRs, List[FileContents]]:
    """Compile Python module(s) to the source of Python C extension modules.

    This generates the source code for the "shared library" module
    for each group. The shim modules are generated in mypyc.build.
    Each shared library module provides, for each module in its group,
    a PyCapsule containing an initialization function.
    Additionally, it provides a capsule containing an export table of
    pointers to all of the group's functions and static variables.

    Arguments:
        result: The BuildResult from the mypy front-end
        compiler_options: The compilation options
        errors: Where to report any errors encountered
        groups: The groups that we are compiling. See documentation of Groups type above.
        ops: Optionally, where to dump stringified ops for debugging.

    Returns the IR of the modules and a list containing the generated files for each group.
    """
    module_names = [
        source.module for group_sources, _ in groups
        for source in group_sources
    ]
    file_nodes = [result.files[name] for name in module_names]

    # Construct a map from modules to what group they belong to
    group_map = {}
    for group, lib_name in groups:
        for source in group:
            group_map[source.module] = lib_name

    # Generate basic IR, with missing exception and refcount handling.
    mapper = genops.Mapper(group_map)
    modules = genops.build_ir(file_nodes, result.graph, result.types, mapper,
                              compiler_options, errors)
    if errors.num_errors > 0:
        return modules, []
    # Insert uninit checks.
    for module in modules.values():
        for fn in module.functions:
            insert_uninit_checks(fn)
    # Insert exception handling.
    for module in modules.values():
        for fn in module.functions:
            insert_exception_handling(fn)
    # Insert refcount handling.
    for module in modules.values():
        for fn in module.functions:
            insert_ref_count_opcodes(fn)

    source_paths = {
        module_name: result.files[module_name].path
        for module_name in module_names
    }

    names = NameGenerator([[source.module for source in sources]
                           for sources, _ in groups])

    # Generate C code for each compilation group. Each group will be
    # compiled into a separate extension module.
    ctext = []
    for group_sources, group_name in groups:
        group_modules = [(source.module, modules[source.module])
                         for source in group_sources]
        literals = mapper.literals[group_name]
        generator = GroupGenerator(literals, group_modules, source_paths,
                                   group_name, group_map, names,
                                   compiler_options.multi_file)
        ctext.append(generator.generate_c_for_modules())
    return modules, ctext
Beispiel #18
0
 def cname(self, names: NameGenerator) -> str:
     name = self.name
     if self.class_name:
         name += '_' + self.class_name
     return names.private_name(self.module_name, name)
Beispiel #19
0
 def setUp(self) -> None:
     self.context = EmitterContext(NameGenerator([['mod']]))
Beispiel #20
0
 def setUp(self) -> None:
     self.n = Register(int_rprimitive, 'n')
     self.context = EmitterContext(NameGenerator([['mod']]))