COME_FROM for 3.x POP_EXCEPT, DRY with op_name() ...

Start adding COME_FROMs for POP_EXCEPT in preparation for
getting tryelse blocks correct.

Simpler opname access functions:
  - self.op_name(op) is self.opc.opname[op]
  - self.op_name_from_offset(offset) is self.opc.opname[self.code[offset]]

verify.py: not all offsets are ints
This commit is contained in:
rocky
2017-03-01 05:50:31 -05:00
parent e1111e3f50
commit 160ec0d9cc
4 changed files with 34 additions and 19 deletions

View File

@@ -66,6 +66,12 @@ class Scanner(object):
# FIXME: This weird Python2 behavior is not Python3 # FIXME: This weird Python2 behavior is not Python3
self.resetTokenClass() self.resetTokenClass()
def opname_for_offset(self, offset):
return self.opc.opname[self.code[offset]]
def op_name(self, op):
return self.opc.opname[op]
def is_jump_forward(self, offset): def is_jump_forward(self, offset):
""" """
Return True if the code at offset is some sort of jump forward. Return True if the code at offset is some sort of jump forward.

View File

@@ -164,7 +164,7 @@ class Scanner2(scan.Scanner):
# continue # continue
# last_offset = jump_offset # last_offset = jump_offset
come_from_name = 'COME_FROM' come_from_name = 'COME_FROM'
op_name = self.opc.opname[self.code[jump_offset]] op_name = self.opname_for_offset(jump_offset)
if op_name.startswith('SETUP_') and self.version == 2.7: if op_name.startswith('SETUP_') and self.version == 2.7:
come_from_type = op_name[len('SETUP_'):] come_from_type = op_name[len('SETUP_'):]
if come_from_type not in ('LOOP', 'EXCEPT'): if come_from_type not in ('LOOP', 'EXCEPT'):
@@ -178,7 +178,7 @@ class Scanner2(scan.Scanner):
pass pass
op = self.code[offset] op = self.code[offset]
op_name = self.opc.opname[op] op_name = self.op_name(op)
oparg = None; pattr = None oparg = None; pattr = None
has_arg = op_has_argument(op, self.opc) has_arg = op_has_argument(op, self.opc)
@@ -406,7 +406,7 @@ class Scanner2(scan.Scanner):
while code[j] == self.opc.JUMP_ABSOLUTE: while code[j] == self.opc.JUMP_ABSOLUTE:
j = self.prev[j] j = self.prev[j]
if (self.version >= 2.3 and if (self.version >= 2.3 and
self.opc.opname[code[j]] == 'LIST_APPEND'): # list comprehension self.opname_for_offset(j) == 'LIST_APPEND'): # list comprehension
stmts.remove(s) stmts.remove(s)
continue continue
elif code[s] == self.opc.POP_TOP: elif code[s] == self.opc.POP_TOP:
@@ -844,7 +844,7 @@ class Scanner2(scan.Scanner):
# is a jump to a SETUP_LOOP target. # is a jump to a SETUP_LOOP target.
next_offset = target + self.op_size(self.code[target]) next_offset = target + self.op_size(self.code[target])
next_op = self.code[next_offset] next_op = self.code[next_offset]
if self.opc.opname[next_op] == 'JUMP_FORWARD': if self.op_name(next_op) == 'JUMP_FORWARD':
jump_target = self.get_target(next_offset, next_op) jump_target = self.get_target(next_offset, next_op)
if jump_target in self.setup_loops: if jump_target in self.setup_loops:
self.structs.append({'type': 'while-loop', self.structs.append({'type': 'while-loop',
@@ -882,12 +882,12 @@ class Scanner2(scan.Scanner):
# 39_0 COME_FROM 3 # 39_0 COME_FROM 3
# 40 ... # 40 ...
if self.opc.opname[code[jump_if_offset]].startswith('JUMP_IF'): if self.opname_for_offset(jump_if_offset).startswith('JUMP_IF'):
jump_if_target = code[jump_if_offset+1] jump_if_target = code[jump_if_offset+1]
if self.opc.opname[code[jump_if_target + jump_if_offset + 3]] == 'POP_TOP': if self.opname_for_offset(jump_if_target + jump_if_offset + 3) == 'POP_TOP':
jump_inst = jump_if_target + jump_if_offset jump_inst = jump_if_target + jump_if_offset
jump_offset = code[jump_inst+1] jump_offset = code[jump_inst+1]
jump_op = self.opc.opname[code[jump_inst]] jump_op = self.opname_for_offset(jump_inst)
if (jump_op == 'JUMP_FORWARD' and jump_offset == 1): if (jump_op == 'JUMP_FORWARD' and jump_offset == 1):
self.structs.append({'type': 'if-then', self.structs.append({'type': 'if-then',
'start': start-3, 'start': start-3,
@@ -922,7 +922,7 @@ class Scanner2(scan.Scanner):
# 256 # 256
if if_then_maybe and jump_op == 'JUMP_ABSOLUTE': if if_then_maybe and jump_op == 'JUMP_ABSOLUTE':
jump_target = self.get_target(jump_inst, code[jump_inst]) jump_target = self.get_target(jump_inst, code[jump_inst])
if self.opc.opname[code[end]] == 'JUMP_FORWARD': if self.opname_for_offset(end) == 'JUMP_FORWARD':
end_target = self.get_target(end, code[end]) end_target = self.get_target(end, code[end])
if jump_target == end_target: if jump_target == end_target:
self.structs.append(if_then_maybe) self.structs.append(if_then_maybe)
@@ -991,7 +991,7 @@ class Scanner2(scan.Scanner):
oparg = self.get_argument(offset) oparg = self.get_argument(offset)
if label is None: if label is None:
if op in self.opc.hasjrel and self.opc.opname[op] != 'FOR_ITER': if op in self.opc.hasjrel and self.op_name(op) != 'FOR_ITER':
# if (op in self.opc.hasjrel and # if (op in self.opc.hasjrel and
# (self.version < 2.0 or op != self.opc.FOR_ITER)): # (self.version < 2.0 or op != self.opc.FOR_ITER)):
label = offset + 3 + oparg label = offset + 3 + oparg

View File

@@ -133,9 +133,6 @@ class Scanner3(Scanner):
# FIXME: remove the above in favor of: # FIXME: remove the above in favor of:
# self.varargs_ops = frozenset(self.opc.hasvargs) # self.varargs_ops = frozenset(self.opc.hasvargs)
def opName(self, offset):
return self.opc.opname[self.code[offset]]
def ingest(self, co, classname=None, code_objects={}, show_asm=None): def ingest(self, co, classname=None, code_objects={}, show_asm=None):
""" """
Pick out tokens from an uncompyle6 code object, and transform them, Pick out tokens from an uncompyle6 code object, and transform them,
@@ -219,7 +216,7 @@ class Scanner3(Scanner):
# "loop" tag last so the grammar rule matches that properly. # "loop" tag last so the grammar rule matches that properly.
for jump_offset in sorted(jump_targets[inst.offset], reverse=True): for jump_offset in sorted(jump_targets[inst.offset], reverse=True):
come_from_name = 'COME_FROM' come_from_name = 'COME_FROM'
opname = self.opName(jump_offset) opname = self.opname_for_offset(jump_offset)
if opname.startswith('SETUP_'): if opname.startswith('SETUP_'):
come_from_type = opname[len('SETUP_'):] come_from_type = opname[len('SETUP_'):]
come_from_name = 'COME_FROM_%s' % come_from_type come_from_name = 'COME_FROM_%s' % come_from_type
@@ -902,6 +899,14 @@ class Scanner3(Scanner):
target = self.get_target(offset) target = self.get_target(offset)
end = self.restrict_to_parent(target, parent) end = self.restrict_to_parent(target, parent)
self.fixed_jumps[offset] = end self.fixed_jumps[offset] = end
elif op == self.opc.POP_EXCEPT:
if self.version <= 3.5:
next_offset = offset+1
else:
next_offset = offset+2
target = self.get_target(next_offset)
if target > next_offset:
self.fixed_jumps[next_offset] = target
elif op == self.opc.SETUP_FINALLY: elif op == self.opc.SETUP_FINALLY:
target = self.get_target(offset) target = self.get_target(offset)
end = self.restrict_to_parent(target, parent) end = self.restrict_to_parent(target, parent)

View File

@@ -331,18 +331,22 @@ def cmp_code_objects(version, is_pypy, code_obj1, code_obj2,
raise CmpErrorCode(name, tokens1[i1].offset, tokens1[i1], raise CmpErrorCode(name, tokens1[i1].offset, tokens1[i1],
tokens2[i2], tokens1, tokens2) tokens2[i2], tokens1, tokens2)
elif tokens1[i1].type in JUMP_OPs and tokens1[i1].pattr != tokens2[i2].pattr: elif tokens1[i1].type in JUMP_OPs and tokens1[i1].pattr != tokens2[i2].pattr:
dest1 = int(tokens1[i1].pattr)
dest2 = int(tokens2[i2].pattr)
if tokens1[i1].type == 'JUMP_BACK': if tokens1[i1].type == 'JUMP_BACK':
dest1 = int(tokens1[i1].pattr)
dest2 = int(tokens2[i2].pattr)
if offset_map[dest1] != dest2: if offset_map[dest1] != dest2:
raise CmpErrorCode(name, tokens1[i1].offset, tokens1[i1], raise CmpErrorCode(name, tokens1[i1].offset, tokens1[i1],
tokens2[i2], tokens1, tokens2) tokens2[i2], tokens1, tokens2)
else: else:
# import pdb; pdb.set_trace() # import pdb; pdb.set_trace()
if dest1 in check_jumps: try:
check_jumps[dest1].append((i1, i2, dest2)) dest1 = int(tokens1[i1].pattr)
else: if dest1 in check_jumps:
check_jumps[dest1] = [(i1, i2, dest2)] check_jumps[dest1].append((i1, i2, dest2))
else:
check_jumps[dest1] = [(i1, i2, dest2)]
except:
pass
i1 += 1 i1 += 1
i2 += 1 i2 += 1