def extract_prelude(cls, bytecode, co): ip = 0 ip, n_state = upyopcodes.decode_varint(bytecode, ip) ip, n_exc_stack = upyopcodes.decode_varint(bytecode, ip) scope_flags = bytecode[ip]; ip += 1 n_pos_args = bytecode[ip]; ip += 1 n_kwonly_args = bytecode[ip]; ip += 1 n_def_pos_args = bytecode[ip]; ip += 1 ip2, code_info_size = upyopcodes.decode_varint(bytecode, ip) ip += code_info_size while bytecode[ip] != 0xff: ip += 1 ip += 1 # ip now points to first opcode # ip2 points to simple_name qstr co.mpy_stacksize = n_state co.mpy_excstacksize = n_exc_stack # Despite CPython docs saying "co_stacksize is the required stack # size (including local variables)", it's actually doesn't include # local variables (which function arguments being such too). This # was reported as https://bugs.python.org/issue38316 . # We don't readily have a number of local vars here, so at least # subtract number of arguments. co.co_stacksize = n_state - (n_pos_args + n_kwonly_args) co.co_argcount = n_pos_args co.co_kwonlyargcount = n_kwonly_args co.co_flags = scope_flags co.mpy_def_pos_args = n_def_pos_args return ip, ip2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args, code_info_size)
def disassemble(code, real_qstrs=False, qstr_ids=True): i = 0 bc = code.co_code while i < len(bc): typ, sz = upyopcodes.mp_opcode_format(bc, i) # Handled by mp_opcode_format() above, but # config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE # must be set correctly! #if bc[i] in upyopcodes.hascache: # sz += 1 print("% 15d " % i, end="") optarg = None opcode_str = opname[bc[i]] if typ == upyopcodes.MP_OPCODE_BYTE: # May have implict value encoded in the opcode implicit = op_implicit_arg[bc[i]] if implicit is not None: optarg = implicit elif typ == upyopcodes.MP_OPCODE_QSTR: optarg = bc[i + 1] + (bc[i + 2] << 8) if real_qstrs: s = qstr_by_id(optarg) else: s = code.co_names[optarg] if qstr_ids: optarg = "%d (%s)" % (optarg, s) else: optarg = s elif typ == upyopcodes.MP_OPCODE_VAR_UINT: signed = False if opcode_str == "LOAD_CONST_SMALL_INT": signed = True next_i, optarg = upyopcodes.decode_varint(bc, i + 1, signed=signed) if opcode_str.startswith("CALL_FUNCTION"): optarg = "n=%d nkw=%d" % (optarg & 0xff, optarg >> 8) elif opcode_str in ("LOAD_CONST_OBJ", "MAKE_FUNCTION", "MAKE_FUNCTION_DEFARGS", "MAKE_CLOSURE"): optarg = "%d (%r)" % (optarg, code.co_consts[optarg]) if opcode_str == "MAKE_CLOSURE": optarg += " n_closed=%d " % bc[next_i] elif typ == upyopcodes.MP_OPCODE_OFFSET: optarg = bc[i + 1] + (bc[i + 2] << 8) - 0x8000 + (i + sz) else: assert 0 if optarg is not None: print("%-24s %s" % (opcode_str, optarg), end="") else: print("%-24s" % opcode_str, end="") if 0: print(" # t=%d sz=%d" % (typ, sz), end="") print() i += sz