Ejemplo n.º 1
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,))
Ejemplo n.º 2
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.
         #
         switches = [
             link for link in block.exits if link.exitcase != 'default'
         ]
         switches.sort(key=lambda link: link.llexitcase)
         kind = getkind(block.exitswitch.concretetype)
         assert kind == 'int'  # XXX
         #
         # A switch on an integer, implementable efficiently with the
         # help of a SwitchDictDescr.  We use this even if there are
         # very few cases: in pyjitpl.py, opimpl_switch() will promote
         # the int only if it matches one of the cases.
         from rpython.jit.codewriter.jitcode import SwitchDictDescr
         switchdict = SwitchDictDescr()
         switchdict._labels = []
         self.emitline('-live-')  # for 'guard_value'
         self.emitline('switch', self.getcolor(block.exitswitch),
                       switchdict)
         # emit the default path
         if block.exits[-1].exitcase == 'default':
             self.make_link(block.exits[-1])
         else:
             self.emitline("unreachable")
             self.emitline("---")
         #
         for switch in switches:
             key = lltype.cast_primitive(lltype.Signed, switch.llexitcase)
             switchdict._labels.append((key, TLabel(switch)))
             # emit code for that path
             # note: we need a -live- for all the 'guard_false' we produce
             # if the switched value doesn't match any case.
             self.emitline(Label(switch))
             self.emitline('-live-')
             self.make_link(switch)
Ejemplo 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.canraise:
         # 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.
         #
         switches = [link for link in block.exits
                     if link.exitcase != 'default']
         switches.sort(key=lambda link: link.llexitcase)
         kind = getkind(block.exitswitch.concretetype)
         assert kind == 'int'    # XXX
         #
         # A switch on an integer, implementable efficiently with the
         # help of a SwitchDictDescr.  We use this even if there are
         # very few cases: in pyjitpl.py, opimpl_switch() will promote
         # the int only if it matches one of the cases.
         from rpython.jit.codewriter.jitcode import SwitchDictDescr
         switchdict = SwitchDictDescr()
         switchdict._labels = []
         self.emitline('-live-')    # for 'guard_value'
         self.emitline('switch', self.getcolor(block.exitswitch),
                                 switchdict)
         # emit the default path
         if block.exits[-1].exitcase == 'default':
             self.make_link(block.exits[-1])
         else:
             self.emitline("unreachable")
             self.emitline("---")
         #
         for switch in switches:
             key = lltype.cast_primitive(lltype.Signed,
                                         switch.llexitcase)
             switchdict._labels.append((key, TLabel(switch)))
             # emit code for that path
             # note: we need a -live- for all the 'guard_false' we produce
             # if the switched value doesn't match any case.
             self.emitline(Label(switch))
             self.emitline('-live-')
             self.make_link(switch)