Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def __iter__(self):
index = 0
while index < len(self):
instr = self[index]
index += 1
if not isinstance(instr, (SetLineno, Instr, ConcreteInstr)):
raise ValueError("BasicBlock must only contain SetLineno, "
"Instr and ConcreteInstr objects, "
"but %s was found"
% instr.__class__.__name__)
if isinstance(instr, Instr) and instr.has_jump():
if index < len(self):
raise ValueError("Only the last instruction of a basic "
"block can be a jump")
if not isinstance(instr.arg, BasicBlock):
raise ValueError("Jump target must a BasicBlock, got %s",
type(instr.arg).__name__)
yield instr
if target_block is not None:
used_blocks.add(id(target_block))
labels = {}
jumps = []
instructions = []
for block in self:
if id(block) in used_blocks:
new_label = Label()
labels[id(block)] = new_label
instructions.append(new_label)
for instr in block:
# don't copy SetLineno objects
if isinstance(instr, (Instr, ConcreteInstr)):
instr = instr.copy()
if isinstance(instr.arg, BasicBlock):
jumps.append(instr)
instructions.append(instr)
# Map to new labels
for instr in jumps:
instr.arg = labels[id(instr.arg)]
bytecode = _bytecode.Bytecode()
bytecode._copy_attr_from(self)
bytecode.argnames = list(self.argnames)
bytecode[:] = instructions
return bytecode
def _check_instr(self, instr):
if not isinstance(instr, (ConcreteInstr, SetLineno)):
raise ValueError(
"ConcreteBytecode must only contain "
"ConcreteInstr and SetLineno objects, "
"but %s was found" % type(instr).__name__
)
raise ValueError("EXTENDED_ARG followed " "by EXTENDED_ARG")
extended_arg = (extended_arg << 8) + instr.arg
else:
extended_arg = instr.arg
del instructions[index]
continue
if extended_arg is not None:
if _WORDCODE:
arg = (extended_arg << 8) + instr.arg
else:
arg = (extended_arg << 16) + instr.arg
extended_arg = None
instr = ConcreteInstr(
instr.name,
arg,
lineno=instr.lineno,
extended_args=nb_extended_args,
)
instructions[index] = instr
nb_extended_args = 0
index += 1
if extended_arg is not None:
raise ValueError("EXTENDED_ARG at the end of the code")
bytecode = ConcreteBytecode()
bytecode.name = code.co_name
bytecode.filename = code.co_filename
def _flat(self):
instructions = []
jumps = []
for block in self:
target_block = block.get_jump()
if target_block is not None:
instr = block[-1]
instr = ConcreteInstr(instr.name, 0, lineno=instr.lineno)
jumps.append((target_block, instr))
instructions.extend(block[:-1])
instructions.append(instr)
else:
instructions.extend(block)
for target_block, instr in jumps:
instr.arg = self.get_block_index(target_block)
return instructions
def get_instructions(self):
instructions = []
jumps = []
for block in self:
target_block = block.get_jump()
if target_block is not None:
instr = block[-1]
instr = ConcreteInstr(instr.name, 0, lineno=instr.lineno)
jumps.append((target_block, instr))
instructions.extend(block[:-1])
instructions.append(instr)
else:
instructions.extend(block)
for target_block, instr in jumps:
instr.arg = self.get_block_index(target_block)
return instructions
def from_code(code, *, extended_arg=False):
line_starts = dict(dis.findlinestarts(code))
# find block starts
instructions = []
offset = 0
lineno = code.co_firstlineno
while offset < len(code.co_code):
if offset in line_starts:
lineno = line_starts[offset]
instr = ConcreteInstr.disassemble(lineno, code.co_code, offset)
instructions.append(instr)
offset += instr.size
# replace jump targets with blocks
# HINT : in some cases Python generate useless EXTENDED_ARG opcode
# with a value of zero. Such opcodes do not increases the size of the
# following opcode the way a normal EXTENDED_ARG does. As a
# consequence, they need to be tracked manually as otherwise the
# offsets in jump targets can end up being wrong.
if not extended_arg:
nb_extended_args = 0
extended_arg = None
index = 0
while index < len(instructions):
instr = instructions[index]
arg = self.add_const(arg)
elif instr.opcode in _opcode.haslocal:
arg = self.add(self.varnames, arg)
elif instr.opcode in _opcode.hasname:
arg = self.add(self.names, arg)
elif instr.opcode in _opcode.hasfree:
if isinstance(arg, CellVar):
arg = self.bytecode.cellvars.index(arg.name)
else:
assert isinstance(arg, FreeVar)
arg = ncells + self.bytecode.freevars.index(arg.name)
elif instr.opcode in _opcode.hascompare:
if isinstance(arg, Compare):
arg = arg.value
instr = ConcreteInstr(instr.name, arg, lineno=lineno)
if is_jump:
self.jumps.append((len(self.instructions), label, instr))
self.instructions.append(instr)