def last_instr(self, start: int, end: int, instr, target=None, exact=True) -> Optional[int]: """ Find the last <instr> in the block from start to end. <instr> is any python bytecode instruction or a list of opcodes If <instr> is an opcode with a target (like a jump), a target destination can be specified which must match precisely if exact is True, or if exact is False, the instruction which has a target closest to <target> will be returned. Return index to it or None if not found. """ code = self.code # Make sure requested positions do not go out of # code bounds if not (start >= 0 and end <= len(code)): return None if not isinstance(instr, list): instr = [instr] result_offset = None current_distance = self.insts[-1].offset - self.insts[0].offset extended_arg = 0 # FIXME: use self.insts rather than code[] for offset in self.op_range(start, end): op = code[offset] if op == self.opc.EXTENDED_ARG: arg = code2num(code, offset + 1) | extended_arg extended_arg = extended_arg_val(self.opc, arg) continue if op in instr: if target is None: result_offset = offset else: dest = self.get_target(offset, extended_arg) if dest == target: current_distance = 0 result_offset = offset elif not exact: new_distance = abs(target - dest) if new_distance <= current_distance: current_distance = new_distance result_offset = offset pass pass pass pass extended_arg = 0 pass return result_offset
def all_instr(self, start, end, instr, target=None, include_beyond_target=False): """ Find all `instr` in the block from start to end. `instr` is any Python opcode or a list of opcodes If `instr` is an opcode with a target (like a jump), a target destination can be specified which must match precisely. Return a list with indexes to them or [] if none found. """ code = self.code assert start >= 0 and end <= len(code) try: None in instr except: instr = [instr] result = [] extended_arg = 0 for offset in self.op_range(start, end): op = code[offset] if op == self.opc.EXTENDED_ARG: arg = code2num(code, offset + 1) | extended_arg extended_arg = extended_arg_val(self.opc, arg) continue if op in instr: if target is None: result.append(offset) else: t = self.get_target(offset, extended_arg) if include_beyond_target and t >= target: result.append(offset) elif t == target: result.append(offset) pass pass pass extended_arg = 0 pass return result