Exemplo n.º 1
0
Arquivo: format.py Projeto: njues/Sypy
 def unformat_arg(s):
     if s.endswith(','):
         s = s[:-1].rstrip()
     if s[0] == '%':
         try:
             return registers[s]
         except KeyError:
             num = int(s[2:])
             if s[1] == 'i': reg = Register('int', num)
             elif s[1] == 'r': reg = Register('ref', num)
             elif s[1] == 'f': reg = Register('float', num)
             else: raise AssertionError("bad register type")
             registers[s] = reg
             return reg
     elif s[0] == '$':
         intvalue = int(s[1:])
         return Constant(intvalue, lltype.Signed)
     elif s[0] == 'L':
         return TLabel(s)
     elif s[0] in 'IRF' and s[1] == '[' and s[-1] == ']':
         items = split_words(s[2:-1])
         items = map(unformat_arg, items)
         return ListOfKind({
             'I': 'int',
             'R': 'ref',
             'F': 'float'
         }[s[0]], items)
     elif s.startswith('<SwitchDictDescr '):
         assert s.endswith('>')
         switchdict = SwitchDictDescr()
         switchdict._labels = []
         items = split_words(s[len('<SwitchDictDescr '):-1])
         for item in items:
             key, value = item.split(':')
             value = value.rstrip(',')
             switchdict._labels.append((int(key), TLabel(value)))
         return switchdict
     else:
         raise AssertionError("unsupported argument: %r" % (s, ))
Exemplo n.º 2
0
 def unformat_arg(s):
     if s.endswith(','):
         s = s[:-1].rstrip()
     if s[0] == '%':
         try:
             return registers[s]
         except KeyError:
             num = int(s[2:])
             if s[1] == 'i': reg = Register('int', num)
             elif s[1] == 'r': reg = Register('ref', num)
             elif s[1] == 'f': reg = Register('float', num)
             else: raise AssertionError("bad register type")
             registers[s] = reg
             return reg
     elif s[0] == '$':
         intvalue = int(s[1:])
         return Constant(intvalue, lltype.Signed)
     elif s[0] == 'L':
         return TLabel(s)
     elif s[0] in 'IRF' and s[1] == '[' and s[-1] == ']':
         items = split_words(s[2:-1])
         items = map(unformat_arg, items)
         return ListOfKind({'I': 'int', 'R': 'ref', 'F': 'float'}[s[0]],
                           items)
     elif s.startswith('<SwitchDictDescr '):
         assert s.endswith('>')
         switchdict = SwitchDictDescr()
         switchdict._labels = []
         items = split_words(s[len('<SwitchDictDescr '):-1])
         for item in items:
             key, value = item.split(':')
             value = value.rstrip(',')
             switchdict._labels.append((int(key), TLabel(value)))
         return switchdict
     else:
         raise AssertionError("unsupported argument: %r" % (s,))
Exemplo n.º 3
0
 def insert_exits(self, block):
     if len(block.exits) == 1:
         # A single link, fall-through
         link = block.exits[0]
         assert link.exitcase in (None, False, True)
         # the cases False or True should not really occur, but can show
         # up in the manually hacked graphs for generators...
         self.make_link(link)
     #
     elif block.exitswitch is c_last_exception:
         # An exception block. See test_exc_exitswitch in test_flatten.py
         # for an example of what kind of code this makes.
         index = -1
         while True:
             lastopname = block.operations[index].opname
             if lastopname != '-live-':
                 break
             index -= 1
         assert block.exits[0].exitcase is None # is this always True?
         #
         if not self._include_all_exc_links:
             if index == -1:
                 # cannot raise: the last instruction is not
                 # actually a '-live-'
                 self.make_link(block.exits[0])
                 return
         # 
         self.emitline('catch_exception', TLabel(block.exits[0]))
         self.make_link(block.exits[0])
         self.emitline(Label(block.exits[0]))
         for link in block.exits[1:]:
             if (link.exitcase is Exception or
                 (link.exitcase is OverflowError and
                  lastopname.startswith('int_') and
                  lastopname.endswith('_ovf'))):
                 # this link captures all exceptions
                 self.make_exception_link(link)
                 break
             self.emitline('goto_if_exception_mismatch',
                           Constant(link.llexitcase,
                                    lltype.typeOf(link.llexitcase)),
                           TLabel(link))
             self.make_exception_link(link)
             self.emitline(Label(link))
         else:
             # no link captures all exceptions, so we have to put a reraise
             # for the other exceptions
             self.emitline("reraise")
             self.emitline("---")
     #
     elif len(block.exits) == 2 and (
             isinstance(block.exitswitch, tuple) or
             block.exitswitch.concretetype == lltype.Bool):
         # Two exit links with a boolean condition
         linkfalse, linktrue = block.exits
         if linkfalse.llexitcase == True:
             linkfalse, linktrue = linktrue, linkfalse
         opname = 'goto_if_not'
         livebefore = False
         if isinstance(block.exitswitch, tuple):
             # special case produced by jtransform.optimize_goto_if_not()
             opname = 'goto_if_not_' + block.exitswitch[0]
             opargs = block.exitswitch[1:]
             if opargs[-1] == '-live-before':
                 livebefore = True
                 opargs = opargs[:-1]
         else:
             assert block.exitswitch.concretetype == lltype.Bool
             opargs = [block.exitswitch]
         #
         lst = self.flatten_list(opargs) + [TLabel(linkfalse)]
         if livebefore:
             self.emitline('-live-')
         self.emitline(opname, *lst)
         if not livebefore:
             self.emitline('-live-', TLabel(linkfalse))
         # true path:
         self.make_link(linktrue)
         # false path:
         self.emitline(Label(linkfalse))
         self.make_link(linkfalse)
     #
     else:
         # A switch.
         #
         def emitdefaultpath():
             if block.exits[-1].exitcase == 'default':
                 self.make_link(block.exits[-1])
             else:
                 self.emitline("unreachable")
                 self.emitline("---")
         #
         self.emitline('-live-')
         switches = [link for link in block.exits
                     if link.exitcase != 'default']
         switches.sort(key=lambda link: link.llexitcase)
         kind = getkind(block.exitswitch.concretetype)
         if len(switches) >= 5 and kind == 'int':
             # A large switch on an integer, implementable efficiently
             # with the help of a SwitchDictDescr
             from pypy.jit.codewriter.jitcode import SwitchDictDescr
             switchdict = SwitchDictDescr()
             switchdict._labels = []
             self.emitline('switch', self.getcolor(block.exitswitch),
                                     switchdict)
             emitdefaultpath()
             #
             for switch in switches:
                 key = lltype.cast_primitive(lltype.Signed,
                                             switch.llexitcase)
                 switchdict._labels.append((key, TLabel(switch)))
                 # emit code for that path
                 self.emitline(Label(switch))
                 self.make_link(switch)
         #
         else:
             # A switch with several possible answers, though not too
             # many of them -- a chain of int_eq comparisons is fine
             assert kind == 'int'    # XXX
             color = self.getcolor(block.exitswitch)
             self.emitline('int_guard_value', color)
             for switch in switches:
                 # make the case described by 'switch'
                 self.emitline('goto_if_not_int_eq',
                               color,
                               Constant(switch.llexitcase,
                                        block.exitswitch.concretetype),
                               TLabel(switch))
                 # emit code for the "taken" path
                 self.make_link(switch)
                 # finally, emit the label for the "non-taken" path
                 self.emitline(Label(switch))
             #
             emitdefaultpath()
Exemplo n.º 4
0
    def insert_exits(self, block):
        if len(block.exits) == 1:
            # A single link, fall-through
            link = block.exits[0]
            assert link.exitcase in (None, False, True)
            # the cases False or True should not really occur, but can show
            # up in the manually hacked graphs for generators...
            self.make_link(link)
        #
        elif block.exitswitch is c_last_exception:
            # An exception block. See test_exc_exitswitch in test_flatten.py
            # for an example of what kind of code this makes.
            index = -1
            while True:
                lastopname = block.operations[index].opname
                if lastopname != '-live-':
                    break
                index -= 1
            assert block.exits[0].exitcase is None  # is this always True?
            #
            if not self._include_all_exc_links:
                if index == -1:
                    # cannot raise: the last instruction is not
                    # actually a '-live-'
                    self.make_link(block.exits[0])
                    return
            #
            self.emitline('catch_exception', TLabel(block.exits[0]))
            self.make_link(block.exits[0])
            self.emitline(Label(block.exits[0]))
            for link in block.exits[1:]:
                if (link.exitcase is Exception
                        or (link.exitcase is OverflowError
                            and lastopname.startswith('int_')
                            and lastopname.endswith('_ovf'))):
                    # this link captures all exceptions
                    self.make_exception_link(link)
                    break
                self.emitline(
                    'goto_if_exception_mismatch',
                    Constant(link.llexitcase, lltype.typeOf(link.llexitcase)),
                    TLabel(link))
                self.make_exception_link(link)
                self.emitline(Label(link))
            else:
                # no link captures all exceptions, so we have to put a reraise
                # for the other exceptions
                self.emitline("reraise")
                self.emitline("---")
        #
        elif len(block.exits) == 2 and (isinstance(block.exitswitch, tuple)
                                        or block.exitswitch.concretetype
                                        == lltype.Bool):
            # Two exit links with a boolean condition
            linkfalse, linktrue = block.exits
            if linkfalse.llexitcase == True:
                linkfalse, linktrue = linktrue, linkfalse
            opname = 'goto_if_not'
            livebefore = False
            if isinstance(block.exitswitch, tuple):
                # special case produced by jtransform.optimize_goto_if_not()
                opname = 'goto_if_not_' + block.exitswitch[0]
                opargs = block.exitswitch[1:]
                if opargs[-1] == '-live-before':
                    livebefore = True
                    opargs = opargs[:-1]
            else:
                assert block.exitswitch.concretetype == lltype.Bool
                opargs = [block.exitswitch]
            #
            lst = self.flatten_list(opargs) + [TLabel(linkfalse)]
            if livebefore:
                self.emitline('-live-')
            self.emitline(opname, *lst)
            if not livebefore:
                self.emitline('-live-', TLabel(linkfalse))
            # true path:
            self.make_link(linktrue)
            # false path:
            self.emitline(Label(linkfalse))
            self.make_link(linkfalse)
        #
        else:
            # A switch.
            #
            def emitdefaultpath():
                if block.exits[-1].exitcase == 'default':
                    self.make_link(block.exits[-1])
                else:
                    self.emitline("unreachable")
                    self.emitline("---")

            #
            self.emitline('-live-')
            switches = [
                link for link in block.exits if link.exitcase != 'default'
            ]
            switches.sort(key=lambda link: link.llexitcase)
            kind = getkind(block.exitswitch.concretetype)
            if len(switches) >= 5 and kind == 'int':
                # A large switch on an integer, implementable efficiently
                # with the help of a SwitchDictDescr
                from pypy.jit.codewriter.jitcode import SwitchDictDescr
                switchdict = SwitchDictDescr()
                switchdict._labels = []
                self.emitline('switch', self.getcolor(block.exitswitch),
                              switchdict)
                emitdefaultpath()
                #
                for switch in switches:
                    key = lltype.cast_primitive(lltype.Signed,
                                                switch.llexitcase)
                    switchdict._labels.append((key, TLabel(switch)))
                    # emit code for that path
                    self.emitline(Label(switch))
                    self.make_link(switch)
            #
            else:
                # A switch with several possible answers, though not too
                # many of them -- a chain of int_eq comparisons is fine
                assert kind == 'int'  # XXX
                color = self.getcolor(block.exitswitch)
                self.emitline('int_guard_value', color)
                for switch in switches:
                    # make the case described by 'switch'
                    self.emitline(
                        'goto_if_not_int_eq', color,
                        Constant(switch.llexitcase,
                                 block.exitswitch.concretetype),
                        TLabel(switch))
                    # emit code for the "taken" path
                    self.make_link(switch)
                    # finally, emit the label for the "non-taken" path
                    self.emitline(Label(switch))
                #
                emitdefaultpath()