예제 #1
0
    def test_stack_effects(self):
        # Verify all opcodes are handled and that "jump=None" really returns
        # the max of the other cases.
        from bytecode.concrete import ConcreteInstr

        def check(instr):
            jump = instr.stack_effect(jump=True)
            no_jump = instr.stack_effect(jump=False)
            max_effect = instr.stack_effect(jump=None)
            self.assertEqual(instr.stack_effect(), max_effect)
            self.assertEqual(max_effect, max(jump, no_jump))

            if not instr.has_jump():
                self.assertEqual(jump, no_jump)

        for name, op in opcode.opmap.items():
            with self.subTest(name):
                # Use ConcreteInstr instead of Instr because it doesn't care
                # what kind of argument it is constructed with.
                if op < opcode.HAVE_ARGUMENT:
                    check(ConcreteInstr(name))
                else:
                    for arg in range(256):
                        check(ConcreteInstr(name, arg))

        # LOAD_CONST uses a concrete python object as its oparg, however, in
        #       dis.stack_effect(opcode.opmap['LOAD_CONST'], oparg),
        # oparg should be the index of that python object in the constants.
        #
        # Fortunately, for an instruction whose oparg isn't equivalent to its
        # form in binary files(pyc format), the stack effect is a
        # constant which does not depend on its oparg.
        #
        # The second argument of dis.stack_effect cannot be
        # more than 2**31 - 1. If stack effect of an instruction is
        # independent of its oparg, we pass 0 as the second argument
        # of dis.stack_effect.
        # (As a result we can calculate stack_effect for
        #  any LOAD_CONST instructions, even for large integers)

        for arg in 2**31, 2**32, 2**63, 2**64, -1:
            self.assertEqual(Instr("LOAD_CONST", arg).stack_effect(), 1)
예제 #2
0
    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
예제 #3
0
파일: cfg.py 프로젝트: adamchainz/bytecode
    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
예제 #4
0
    def test_stack_effects(self):
        # Verify all opcodes are handled and that "jump=None" really returns
        # the max of the other cases.
        from bytecode.concrete import ConcreteInstr
        for name, op in opcode.opmap.items():
            # Use ConcreteInstr instead of Instr because it doesn't care what
            # kind of argument it is constructed with.
            if op < opcode.HAVE_ARGUMENT:
                instr = ConcreteInstr(name)
            else:
                instr = ConcreteInstr(name, 0)
            jump = instr.stack_effect(jump=True)
            no_jump = instr.stack_effect(jump=False)
            max_effect = instr.stack_effect(jump=None)
            msg = "op=%s" % name
            self.assertEqual(instr.stack_effect(), max_effect, msg)
            self.assertEqual(max_effect, max(jump, no_jump), msg)

            if not instr.has_jump():
                self.assertEqual(jump, no_jump, msg)