def read_bytecode(self, bc_len): qstr_cnt = 0 qstrs = [] self.cnt = 0 bc_buf = bytearray() while len(bc_buf) < bc_len: opcode = self.read_byte(bc_buf) typ, extra = upyopcodes.mp_opcode_type(opcode) dprint("%02d-%02d: opcode: %02x type: %d, extra: %d" % (self.cnt, len(bc_buf), opcode, typ, extra)) if typ == upyopcodes.MP_OPCODE_QSTR: qstrs.append(self.read_qstr()) # Patch in CodeType-local qstr id, kinda similar to CPython bc_buf.append(qstr_cnt & 0xff) bc_buf.append(qstr_cnt >> 8) qstr_cnt += 1 elif typ == upyopcodes.MP_OPCODE_VAR_UINT: self.read_uint(bc_buf) elif typ == upyopcodes.MP_OPCODE_OFFSET: self.read_byte(bc_buf) self.read_byte(bc_buf) elif typ == upyopcodes.MP_OPCODE_BYTE: pass else: assert 0 for _ in range(extra): self.read_byte(bc_buf) return bc_buf, tuple(qstrs)
def read_bytecode(self, bc_len): qstr_cnt = 0 qstrs = [] self.cnt = 0 bc_buf = bytearray() while len(bc_buf) < bc_len: opcode = self.read_byte(bc_buf) typ, extra = upyopcodes.mp_opcode_type(opcode) dprint("%02d-%02d: opcode: %02x type: %d, extra: %d" % (self.cnt, len(bc_buf), opcode, typ, extra)) if typ == upyopcodes.MP_OPCODE_QSTR: qstrs.append(self.read_qstr()) # Patch in CodeType-local qstr id, kinda similar to CPython bc_buf.append(qstr_cnt & 0xff) bc_buf.append(qstr_cnt >> 8) qstr_cnt += 1 elif typ == upyopcodes.MP_OPCODE_VAR_UINT: self.read_uint(bc_buf) elif typ == upyopcodes.MP_OPCODE_OFFSET: self.read_byte(bc_buf) self.read_byte(bc_buf) elif typ == upyopcodes.MP_OPCODE_BYTE: pass else: assert 0 for _ in range(extra): self.read_byte(bc_buf) return bc_buf, tuple(qstrs)
def add(self, opcode, *args): delta = stack_effect(opcode, *args) self.stk_ptr += delta assert self.stk_ptr >= 0, self.stk_ptr if self.stk_ptr > self.stk_use: self.stk_use = self.stk_ptr self.buf.writebin("B", opcode) if args != (): arg = args[0] fl, extra = upyopcodes.mp_opcode_type(opcode) if opcode in (opmap["CALL_FUNCTION"], opmap["CALL_FUNCTION_VAR_KW"], opmap["CALL_METHOD"], opmap["CALL_METHOD_VAR_KW"]): MPYWriter.write_uint(None, args[0] + (args[1] << 8), self.buf) elif opcode == opmap["LOAD_CONST_SMALL_INT"]: MPYWriter.write_int(None, arg, self.buf) elif opcode == opmap["LOAD_CONST_OBJ"]: MPYWriter.write_uint(None, len(self.mpy_consts), self.buf) self.mpy_consts.append(arg) elif opcode in (opmap["MAKE_FUNCTION"], opmap["MAKE_FUNCTION_DEFARGS"], opmap["MAKE_CLOSURE"], opmap["MAKE_CLOSURE_DEFARGS"]): if self.codeobj_off >= 0: MPYWriter.write_uint(None, len(self.mpy_codeobjs) + self.codeobj_off, self.buf) self.mpy_codeobjs.append(arg) else: MPYWriter.write_uint(None, len(self.mpy_consts), self.buf) self.mpy_consts.append(arg) if opcode in (opmap["MAKE_CLOSURE"], opmap["MAKE_CLOSURE_DEFARGS"]): self.buf.writebin("B", args[1]) elif opcode == opmap["RAISE_VARARGS"]: self.buf.writebin("B", arg) elif fl == upyopcodes.MP_OPCODE_OFFSET: self.buf.writebin("<H", arg) elif fl == upyopcodes.MP_OPCODE_QSTR: if self.only_for_mpy: self.buf.writebin("<H", 0) else: self.buf.writebin("<H", str2qstr(arg)) # cache if opcode in upyopcodes.hascache: self.buf.writebin("B", 0) self.co_names.append(arg) elif fl == upyopcodes.MP_OPCODE_VAR_UINT: MPYWriter.write_uint(None, arg, self.buf) if opcode in (opmap["SETUP_EXCEPT"], opmap["SETUP_FINALLY"], opmap["SETUP_WITH"]): self.exc_stk_ptr += 1 if self.exc_stk_ptr > self.exc_stk_use: self.exc_stk_use = self.exc_stk_ptr elif opcode == opmap["END_FINALLY"]: self.exc_stk_ptr -= 1
def add(self, opcode, *args): delta = stack_effect(opcode, *args) self.stk_ptr += delta assert self.stk_ptr >= 0, self.stk_ptr if self.stk_ptr > self.stk_use: self.stk_use = self.stk_ptr self.buf.writebin("B", opcode) if args != (): arg = args[0] fl, extra = upyopcodes.mp_opcode_type(opcode) if opcode == opmap["CALL_FUNCTION"]: MPYOutput.write_uint(None, args[0] + (args[1] << 8), self.buf) elif opcode == opmap["LOAD_CONST_SMALL_INT"]: MPYOutput.write_int(None, arg, self.buf) elif opcode == opmap["LOAD_CONST_OBJ"]: MPYOutput.write_uint(None, len(self.co_consts), self.buf) self.co_consts.append(arg) elif opcode == opmap["MAKE_FUNCTION"]: MPYOutput.write_uint(None, len(self.co_consts), self.buf) self.co_consts.append(arg) elif fl == upyopcodes.MP_OPCODE_OFFSET: self.buf.writebin("<H", arg) elif fl == upyopcodes.MP_OPCODE_QSTR: if self.only_for_mpy: self.buf.writebin("<H", 0) else: self.buf.writebin("<H", id(sys.intern(arg)) >> 2) # cache if opcode in upyopcodes.hascache: self.buf.writebin("B", 0) self.co_names.append(arg) elif fl == upyopcodes.MP_OPCODE_VAR_UINT: MPYOutput.write_uint(None, arg, self.buf) if opcode in (opmap["SETUP_EXCEPT"], opmap["SETUP_FINALLY"]): self.exc_stk_ptr += 1 if self.exc_stk_ptr > self.exc_stk_use: self.exc_stk_use = self.exc_stk_ptr elif opcode == opmap["END_FINALLY"]: self.exc_stk_ptr -= 1
def pack_bytecode(self, code, buf): bc = code.co_code log.debug("pack_bytecode: in: bc: %s, buf: %s", bc, buf.getvalue()) i = 0 qstr_i = 0 while i < len(bc): opcode = bc[i] buf.writebin("B", opcode) typ, extra = upyopcodes.mp_opcode_type(opcode) log.debug("%02d: opcode: %02x type: %d, extra: %d" % (i, opcode, typ, extra)) i += 1 if typ == upyopcodes.MP_OPCODE_QSTR: self.write_qstr(code.co_names[qstr_i], buf) qstr_i += 1 i += 2 elif typ == upyopcodes.MP_OPCODE_VAR_UINT: while True: b = bc[i] buf.writebin("B", b) i += 1 if b & 0x80 == 0: break elif typ == upyopcodes.MP_OPCODE_OFFSET: buf.writebin("B", bc[i]) buf.writebin("B", bc[i + 1]) i += 2 elif typ == upyopcodes.MP_OPCODE_BYTE: pass else: assert 0 for _ in range(extra): buf.writebin("B", bc[i]) i += 1 log.debug("pack_bytecode: out: buf: %s", buf.getvalue())