Esempio n. 1
0
    def freeze(self, parent_name):
        self.escaped_name = parent_name + self.simple_name.qstr_esc

        # make sure the escaped name is unique
        i = 2
        while self.escaped_name in RawCode.escaped_names:
            self.escaped_name = parent_name + self.simple_name.qstr_esc + str(i)
            i += 1
        RawCode.escaped_names.add(self.escaped_name)

        # emit children first
        for rc in self.raw_codes:
            rc.freeze(self.escaped_name + '_')

        # generate bytecode data
        print()
        print('// frozen bytecode for file %s, scope %s%s' % (self.source_file.str, parent_name, self.simple_name.str))
        print('STATIC ', end='')
        if not config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE:
            print('const ', end='')
        print('byte bytecode_data_%s[%u] = {' % (self.escaped_name, len(self.bytecode)))
        print('   ', end='')
        for i in range(self.ip2):
            print(' 0x%02x,' % self.bytecode[i], end='')
        print()
        print('   ', self.simple_name.qstr_id, '& 0xff,', self.simple_name.qstr_id, '>> 8,')
        print('   ', self.source_file.qstr_id, '& 0xff,', self.source_file.qstr_id, '>> 8,')
        print('   ', end='')
        for i in range(self.ip2 + 4, self.ip):
            print(' 0x%02x,' % self.bytecode[i], end='')
        print()
        ip = self.ip
        while ip < len(self.bytecode):
            f, sz = mp_opcode_format(self.bytecode, ip)
            if f == 1:
                qst = self._unpack_qstr(ip + 1).qstr_id
                print('   ', '0x%02x,' % self.bytecode[ip], qst, '& 0xff,', qst, '>> 8,')
            else:
                print('   ', ''.join('0x%02x, ' % self.bytecode[ip + i] for i in range(sz)))
            ip += sz
        print('};')

        # generate constant objects
        for i, obj in enumerate(self.objs):
            obj_name = 'const_obj_%s_%u' % (self.escaped_name, i)
            if is_str_type(obj) or is_bytes_type(obj):
                if is_str_type(obj):
                    obj = bytes_cons(obj, 'utf8')
                    obj_type = 'mp_type_str'
                else:
                    obj_type = 'mp_type_bytes'
                print('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"};'
                    % (obj_name, obj_type, qstrutil.compute_hash(obj, config.MICROPY_QSTR_BYTES_IN_HASH),
                        len(obj), ''.join(('\\x%02x' % b) for b in obj)))
            elif is_int_type(obj):
                if config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_NONE:
                    # TODO check if we can actually fit this long-int into a small-int
                    raise FreezeError(self, 'target does not support long int')
                elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_LONGLONG:
                    # TODO
                    raise FreezeError(self, 'freezing int to long-long is not implemented')
                elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_MPZ:
                    neg = 0
                    if obj < 0:
                        obj = -obj
                        neg = 1
                    bits_per_dig = config.MPZ_DIG_SIZE
                    digs = []
                    z = obj
                    while z:
                        digs.append(z & ((1 << bits_per_dig) - 1))
                        z >>= bits_per_dig
                    ndigs = len(digs)
                    digs = ','.join(('%#x' % d) for d in digs)
                    print('STATIC const mp_obj_int_t %s = {{&mp_type_int}, '
                        '{.neg=%u, .fixed_dig=1, .alloc=%u, .len=%u, .dig=(uint%u_t[]){%s}}};'
                        % (obj_name, neg, ndigs, ndigs, bits_per_dig, digs))
            elif type(obj) is float:
                print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B')
                print('STATIC const mp_obj_float_t %s = {{&mp_type_float}, %.16g};'
                    % (obj_name, obj))
                print('#endif')
            elif type(obj) is complex:
                print('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};'
                    % (obj_name, obj.real, obj.imag))
            else:
                # TODO
                raise FreezeError(self, 'freezing of object %r is not implemented' % (obj,))

        # generate constant table
        print('STATIC const mp_uint_t const_table_data_%s[%u] = {'
            % (self.escaped_name, len(self.qstrs) + len(self.objs) + len(self.raw_codes)))
        for qst in self.qstrs:
            print('    (mp_uint_t)MP_OBJ_NEW_QSTR(%s),' % global_qstrs[qst].qstr_id)
        for i in range(len(self.objs)):
            if type(self.objs[i]) is float:
                print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B')
                print('    (mp_uint_t)&const_obj_%s_%u,' % (self.escaped_name, i))
                print('#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C')
                n = struct.unpack('<I', struct.pack('<f', self.objs[i]))[0]
                n = ((n & ~0x3) | 2) + 0x80800000
                print('    (mp_uint_t)0x%08x,' % (n,))
                print('#else')
                print('#error "MICROPY_OBJ_REPR_D not supported with floats in frozen mpy files"')
                print('#endif')
            else:
                print('    (mp_uint_t)&const_obj_%s_%u,' % (self.escaped_name, i))
        for rc in self.raw_codes:
            print('    (mp_uint_t)&raw_code_%s,' % rc.escaped_name)
        print('};')

        # generate module
        if self.simple_name.str != '<module>':
            print('STATIC ', end='')
        print('const mp_raw_code_t raw_code_%s = {' % self.escaped_name)
        print('    .kind = MP_CODE_BYTECODE,')
        print('    .scope_flags = 0x%02x,' % self.prelude[2])
        print('    .n_pos_args = %u,' % self.prelude[3])
        print('    .data.u_byte = {')
        print('        .bytecode = bytecode_data_%s,' % self.escaped_name)
        print('        .const_table = const_table_data_%s,' % self.escaped_name)
        print('        #if MICROPY_PERSISTENT_CODE_SAVE')
        print('        .bc_len = %u,' % len(self.bytecode))
        print('        .n_obj = %u,' % len(self.objs))
        print('        .n_raw_code = %u,' % len(self.raw_codes))
        print('        #endif')
        print('    },')
        print('};')
Esempio n. 2
0
    def freeze_constants(self):
        # generate constant objects
        for i, obj in enumerate(self.objs):
            obj_name = 'const_obj_%s_%u' % (self.escaped_name, i)
            if obj is MPFunTable:
                pass
            elif obj is Ellipsis:
                print('#define %s mp_const_ellipsis_obj' % obj_name)
            elif is_str_type(obj) or is_bytes_type(obj):
                if is_str_type(obj):
                    obj = bytes_cons(obj, 'utf8')
                    obj_type = 'mp_type_str'
                else:
                    obj_type = 'mp_type_bytes'
                print('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"};'
                    % (obj_name, obj_type, qstrutil.compute_hash(obj, config.MICROPY_QSTR_BYTES_IN_HASH),
                        len(obj), ''.join(('\\x%02x' % b) for b in obj)))
            elif is_int_type(obj):
                if config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_NONE:
                    # TODO check if we can actually fit this long-int into a small-int
                    raise FreezeError(self, 'target does not support long int')
                elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_LONGLONG:
                    # TODO
                    raise FreezeError(self, 'freezing int to long-long is not implemented')
                elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_MPZ:
                    neg = 0
                    if obj < 0:
                        obj = -obj
                        neg = 1
                    bits_per_dig = config.MPZ_DIG_SIZE
                    digs = []
                    z = obj
                    while z:
                        digs.append(z & ((1 << bits_per_dig) - 1))
                        z >>= bits_per_dig
                    ndigs = len(digs)
                    digs = ','.join(('%#x' % d) for d in digs)
                    print('STATIC const mp_obj_int_t %s = {{&mp_type_int}, '
                        '{.neg=%u, .fixed_dig=1, .alloc=%u, .len=%u, .dig=(uint%u_t*)(const uint%u_t[]){%s}}};'
                        % (obj_name, neg, ndigs, ndigs, bits_per_dig, bits_per_dig, digs))
            elif type(obj) is float:
                print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B')
                print('STATIC const mp_obj_float_t %s = {{&mp_type_float}, %.16g};'
                    % (obj_name, obj))
                print('#endif')
            elif type(obj) is complex:
                print('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};'
                    % (obj_name, obj.real, obj.imag))
            else:
                raise FreezeError(self, 'freezing of object %r is not implemented' % (obj,))

        # generate constant table, if it has any entries
        const_table_len = len(self.qstrs) + len(self.objs) + len(self.raw_codes)
        if const_table_len:
            print('STATIC const mp_rom_obj_t const_table_data_%s[%u] = {'
                % (self.escaped_name, const_table_len))
            for qst in self.qstrs:
                print('    MP_ROM_QSTR(%s),' % global_qstrs[qst].qstr_id)
            for i in range(len(self.objs)):
                if self.objs[i] is MPFunTable:
                    print('    mp_fun_table,')
                elif type(self.objs[i]) is float:
                    print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B')
                    print('    MP_ROM_PTR(&const_obj_%s_%u),' % (self.escaped_name, i))
                    print('#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C')
                    n = struct.unpack('<I', struct.pack('<f', self.objs[i]))[0]
                    n = ((n & ~0x3) | 2) + 0x80800000
                    print('    (mp_rom_obj_t)(0x%08x),' % (n,))
                    print('#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D')
                    n = struct.unpack('<Q', struct.pack('<d', self.objs[i]))[0]
                    n += 0x8004000000000000
                    print('    (mp_rom_obj_t)(0x%016x),' % (n,))
                    print('#endif')
                else:
                    print('    MP_ROM_PTR(&const_obj_%s_%u),' % (self.escaped_name, i))
            for rc in self.raw_codes:
                print('    MP_ROM_PTR(&raw_code_%s),' % rc.escaped_name)
            print('};')
Esempio n. 3
0
def freeze_mpy(base_qstrs, raw_codes):
    # add to qstrs
    new = {}
    for q in global_qstrs:
        # don't add duplicates
        if q is None or q.qstr_esc in base_qstrs or q.qstr_esc in new:
            continue
        new[q.qstr_esc] = (len(new), q.qstr_esc, q.str)
    new = sorted(new.values(), key=lambda x: x[0])

    print('#include "py/bc0.h"')
    print('#include "py/mpconfig.h"')
    print('#include "py/objint.h"')
    print('#include "py/objstr.h"')
    print('#include "py/emitglue.h"')
    print('#include "py/nativeglue.h"')
    print()

    print(
        "#if MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE != %u"
        % config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
    )
    print('#error "incompatible MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE"')
    print("#endif")
    print()

    print("#if MICROPY_LONGINT_IMPL != %u" % config.MICROPY_LONGINT_IMPL)
    print('#error "incompatible MICROPY_LONGINT_IMPL"')
    print("#endif")
    print()

    if config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_MPZ:
        print("#if MPZ_DIG_SIZE != %u" % config.MPZ_DIG_SIZE)
        print('#error "incompatible MPZ_DIG_SIZE"')
        print("#endif")
        print()

    print("#if MICROPY_PY_BUILTINS_FLOAT")
    print("typedef struct _mp_obj_float_t {")
    print("    mp_obj_base_t base;")
    print("    mp_float_t value;")
    print("} mp_obj_float_t;")
    print("#endif")
    print()

    print("#if MICROPY_PY_BUILTINS_COMPLEX")
    print("typedef struct _mp_obj_complex_t {")
    print("    mp_obj_base_t base;")
    print("    mp_float_t real;")
    print("    mp_float_t imag;")
    print("} mp_obj_complex_t;")
    print("#endif")
    print()

    if new:
        print("enum {")
        for i in range(len(new)):
            if i == 0:
                print("    MP_QSTR_%s = MP_QSTRnumber_of," % new[i][1])
            else:
                print("    MP_QSTR_%s," % new[i][1])
        print("};")

    print()
    print("const qstr_attr_t mp_qstr_frozen_const_attr[] = {")
    qstr_size = {"metadata": 0, "data": 0}
    for _, _, qstr in new:
        qbytes = qstrutil.bytes_cons(qstr, "utf8")
        print(
            "    {%d, %d},"
            % (qstrutil.compute_hash(qbytes, config.MICROPY_QSTR_BYTES_IN_HASH), len(qbytes))
        )
        qstr_size["metadata"] += (
            config.MICROPY_QSTR_BYTES_IN_LEN + config.MICROPY_QSTR_BYTES_IN_HASH
        )
        qstr_size["data"] += len(qbytes)
    print("};")

    # As in qstr.c, set so that the first dynamically allocated pool is twice this size; must be <= the len
    qstr_pool_alloc = min(len(new), 10)

    print()
    print("extern const qstr_pool_t mp_qstr_const_pool;")
    print("const qstr_pool_t mp_qstr_frozen_const_pool = {")
    print("    &mp_qstr_const_pool, // previous pool")
    print("    MP_QSTRnumber_of, // previous pool size")
    print("    %u, // allocated entries" % qstr_pool_alloc)
    print("    %u, // used entries" % len(new))
    print("    (qstr_attr_t *)mp_qstr_frozen_const_attr,")
    print("    {")
    for _, _, qstr in new:
        print('        "%s",' % qstrutil.escape_bytes(qstr))
    print("    },")
    print("};")

    for rc in raw_codes:
        rc.freeze(rc.source_file.str.replace("/", "_")[:-3] + "_")

    print()
    print("const char mp_frozen_mpy_names[] = {")
    for rc in raw_codes:
        module_name = rc.source_file.str
        print('"%s\\0"' % module_name)
    print('"\\0"};')

    print("const mp_raw_code_t *const mp_frozen_mpy_content[] = {")
    for rc in raw_codes:
        print("    &raw_code_%s," % rc.escaped_name)
    print("};")

    # If a port defines MICROPY_FROZEN_LIST_ITEM then list all modules wrapped in that macro.
    print("#ifdef MICROPY_FROZEN_LIST_ITEM")
    for rc in raw_codes:
        module_name = rc.source_file.str
        if module_name.endswith("/__init__.py"):
            short_name = module_name[: -len("/__init__.py")]
        else:
            short_name = module_name[: -len(".py")]
        print('MICROPY_FROZEN_LIST_ITEM("%s", "%s")' % (short_name, module_name))
    print("#endif")
Esempio n. 4
0
    def freeze(self, parent_name):
        self.escaped_name = parent_name + self.simple_name.qstr_esc

        # make sure the escaped name is unique
        i = 2
        while self.escaped_name in RawCode.escaped_names:
            self.escaped_name = parent_name + self.simple_name.qstr_esc + str(
                i)
            i += 1
        RawCode.escaped_names.add(self.escaped_name)

        # emit children first
        for rc in self.raw_codes:
            rc.freeze(self.escaped_name + '_')

        # generate bytecode data
        print()
        print('// frozen bytecode for file %s, scope %s%s' %
              (self.source_file.str, parent_name, self.simple_name.str))
        print('STATIC ', end='')
        if not config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE:
            print('const ', end='')
        print('byte bytecode_data_%s[%u] = {' %
              (self.escaped_name, len(self.bytecode)))
        print('   ', end='')
        for i in range(self.ip2):
            print(' 0x%02x,' % self.bytecode[i], end='')
        print()
        print('   ', self.simple_name.qstr_id, '& 0xff,',
              self.simple_name.qstr_id, '>> 8,')
        print('   ', self.source_file.qstr_id, '& 0xff,',
              self.source_file.qstr_id, '>> 8,')
        print('   ', end='')
        for i in range(self.ip2 + 4, self.ip):
            print(' 0x%02x,' % self.bytecode[i], end='')
        print()
        ip = self.ip
        while ip < len(self.bytecode):
            f, sz = mp_opcode_format(self.bytecode, ip)
            if f == 1:
                qst = self._unpack_qstr(ip + 1).qstr_id
                print('   ', '0x%02x,' % self.bytecode[ip], qst, '& 0xff,',
                      qst, '>> 8,')
            else:
                print(
                    '   ', ''.join('0x%02x, ' % self.bytecode[ip + i]
                                   for i in range(sz)))
            ip += sz
        print('};')

        # generate constant objects
        for i, obj in enumerate(self.objs):
            obj_name = 'const_obj_%s_%u' % (self.escaped_name, i)
            if is_str_type(obj) or is_bytes_type(obj):
                if is_str_type(obj):
                    obj = bytes_cons(obj, 'utf8')
                    obj_type = 'mp_type_str'
                else:
                    obj_type = 'mp_type_bytes'
                print(
                    'STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"};'
                    % (obj_name, obj_type,
                       qstrutil.compute_hash(
                           obj, config.MICROPY_QSTR_BYTES_IN_HASH), len(obj),
                       ''.join(('\\x%02x' % b) for b in obj)))
            elif is_int_type(obj):
                if config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_NONE:
                    # TODO check if we can actually fit this long-int into a small-int
                    raise FreezeError(self, 'target does not support long int')
                elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_LONGLONG:
                    # TODO
                    raise FreezeError(
                        self, 'freezing int to long-long is not implemented')
                elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_MPZ:
                    neg = 0
                    if obj < 0:
                        obj = -obj
                        neg = 1
                    bits_per_dig = config.MPZ_DIG_SIZE
                    digs = []
                    z = obj
                    while z:
                        digs.append(z & ((1 << bits_per_dig) - 1))
                        z >>= bits_per_dig
                    ndigs = len(digs)
                    digs = ','.join(('%#x' % d) for d in digs)
                    print(
                        'STATIC const mp_obj_int_t %s = {{&mp_type_int}, '
                        '{.neg=%u, .fixed_dig=1, .alloc=%u, .len=%u, .dig=(uint%u_t[]){%s}}};'
                        % (obj_name, neg, ndigs, ndigs, bits_per_dig, digs))
            elif type(obj) is float:
                print(
                    '#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B'
                )
                print(
                    'STATIC const mp_obj_float_t %s = {{&mp_type_float}, %.16g};'
                    % (obj_name, obj))
                print('#endif')
            elif type(obj) is complex:
                print(
                    'STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};'
                    % (obj_name, obj.real, obj.imag))
            else:
                # TODO
                raise FreezeError(
                    self, 'freezing of object %r is not implemented' % (obj, ))

        # generate constant table
        print('STATIC const mp_uint_t const_table_data_%s[%u] = {' %
              (self.escaped_name,
               len(self.qstrs) + len(self.objs) + len(self.raw_codes)))
        for qst in self.qstrs:
            print('    (mp_uint_t)MP_OBJ_NEW_QSTR(%s),' %
                  global_qstrs[qst].qstr_id)
        for i in range(len(self.objs)):
            if type(self.objs[i]) is float:
                print(
                    '#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B'
                )
                print('    (mp_uint_t)&const_obj_%s_%u,' %
                      (self.escaped_name, i))
                print('#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C')
                n = struct.unpack('<I', struct.pack('<f', self.objs[i]))[0]
                n = ((n & ~0x3) | 2) + 0x80800000
                print('    (mp_uint_t)0x%08x,' % (n, ))
                print('#else')
                print(
                    '#error "MICROPY_OBJ_REPR_D not supported with floats in frozen mpy files"'
                )
                print('#endif')
            else:
                print('    (mp_uint_t)&const_obj_%s_%u,' %
                      (self.escaped_name, i))
        for rc in self.raw_codes:
            print('    (mp_uint_t)&raw_code_%s,' % rc.escaped_name)
        print('};')

        # generate module
        if self.simple_name.str != '<module>':
            print('STATIC ', end='')
        print('const mp_raw_code_t raw_code_%s = {' % self.escaped_name)
        print('    .kind = MP_CODE_BYTECODE,')
        print('    .scope_flags = 0x%02x,' % self.prelude[2])
        print('    .n_pos_args = %u,' % self.prelude[3])
        print('    .data.u_byte = {')
        print('        .bytecode = bytecode_data_%s,' % self.escaped_name)
        print('        .const_table = const_table_data_%s,' %
              self.escaped_name)
        print('        #if MICROPY_PERSISTENT_CODE_SAVE')
        print('        .bc_len = %u,' % len(self.bytecode))
        print('        .n_obj = %u,' % len(self.objs))
        print('        .n_raw_code = %u,' % len(self.raw_codes))
        print('        #endif')
        print('    },')
        print('};')
Esempio n. 5
0
    def freeze_constants(self):
        # generate constant objects
        for i, obj in enumerate(self.objs):
            obj_name = 'const_obj_%s_%u' % (self.escaped_name, i)
            if obj is MPFunTable:
                pass
            elif obj is Ellipsis:
                print('#define %s mp_const_ellipsis_obj' % obj_name)
            elif is_str_type(obj) or is_bytes_type(obj):
                if is_str_type(obj):
                    obj = bytes_cons(obj, 'utf8')
                    obj_type = 'mp_type_str'
                else:
                    obj_type = 'mp_type_bytes'
                print('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"};'
                    % (obj_name, obj_type, qstrutil.compute_hash(obj, config.MICROPY_QSTR_BYTES_IN_HASH),
                        len(obj), ''.join(('\\x%02x' % b) for b in obj)))
            elif is_int_type(obj):
                if config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_NONE:
                    # TODO check if we can actually fit this long-int into a small-int
                    raise FreezeError(self, 'target does not support long int')
                elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_LONGLONG:
                    # TODO
                    raise FreezeError(self, 'freezing int to long-long is not implemented')
                elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_MPZ:
                    neg = 0
                    if obj < 0:
                        obj = -obj
                        neg = 1
                    bits_per_dig = config.MPZ_DIG_SIZE
                    digs = []
                    z = obj
                    while z:
                        digs.append(z & ((1 << bits_per_dig) - 1))
                        z >>= bits_per_dig
                    ndigs = len(digs)
                    digs = ','.join(('%#x' % d) for d in digs)
                    print('STATIC const mp_obj_int_t %s = {{&mp_type_int}, '
                        '{.neg=%u, .fixed_dig=1, .alloc=%u, .len=%u, .dig=(uint%u_t*)(const uint%u_t[]){%s}}};'
                        % (obj_name, neg, ndigs, ndigs, bits_per_dig, bits_per_dig, digs))
            elif type(obj) is float:
                print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B')
                print('STATIC const mp_obj_float_t %s = {{&mp_type_float}, %.16g};'
                    % (obj_name, obj))
                print('#endif')
            elif type(obj) is complex:
                print('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};'
                    % (obj_name, obj.real, obj.imag))
            else:
                raise FreezeError(self, 'freezing of object %r is not implemented' % (obj,))

        # generate constant table, if it has any entries
        const_table_len = len(self.qstrs) + len(self.objs) + len(self.raw_codes)
        if const_table_len:
            print('STATIC const mp_rom_obj_t const_table_data_%s[%u] = {'
                % (self.escaped_name, const_table_len))
            for qst in self.qstrs:
                print('    MP_ROM_QSTR(%s),' % global_qstrs[qst].qstr_id)
            for i in range(len(self.objs)):
                if self.objs[i] is MPFunTable:
                    print('    mp_fun_table,')
                elif type(self.objs[i]) is float:
                    print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B')
                    print('    MP_ROM_PTR(&const_obj_%s_%u),' % (self.escaped_name, i))
                    print('#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C')
                    n = struct.unpack('<I', struct.pack('<f', self.objs[i]))[0]
                    n = ((n & ~0x3) | 2) + 0x80800000
                    print('    (mp_rom_obj_t)(0x%08x),' % (n,))
                    print('#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D')
                    n = struct.unpack('<Q', struct.pack('<d', self.objs[i]))[0]
                    n += 0x8004000000000000
                    print('    (mp_rom_obj_t)(0x%016x),' % (n,))
                    print('#endif')
                else:
                    print('    MP_ROM_PTR(&const_obj_%s_%u),' % (self.escaped_name, i))
            for rc in self.raw_codes:
                print('    MP_ROM_PTR(&raw_code_%s),' % rc.escaped_name)
            print('};')