예제 #1
0
 def visit_bool_literal(self, node, target, *args):
     if target == ir.EXPR:
         return ir.Const(int(node.value), args[0])
     else:
         if node.value:
             return ir.Jump(args[0])
         else:
             return ir.Jump(args[1])
예제 #2
0
 def add_block_to_trace(self, trace, in_block):
     # add block to trace. As a side-effect, tidy up last jump to
     # enforce condition that each cjump must be followed by its
     # false label
     block = copy.copy(in_block)  # avoid modifying block used by caller
     target = block[0].name
     if trace != []:
         lastjump = trace[-1]
         if isinstance(lastjump, ir.Jump):
             if lastjump.dest == target:
                 # remove jumps to the next stm
                 del trace[-1]
         else:
             assert (isinstance(lastjump, ir.CJump))
             if lastjump.falseDest == target:
                 # no change required
                 pass
             elif lastjump.trueDest == target:
                 trace[-1] = self.flip_cjump(lastjump)
             else:
                 # insert extra label and jump to make it work
                 jump = ir.Jump(lastjump.falseDest, lastjump.node)
                 newFalse = self.symbols.newLabel()
                 label = ir.Label(newFalse, lastjump.node)
                 lastjump.falseDest = newFalse
                 trace += [label, jump]
     trace += block
예제 #3
0
    def basic_blocks(self, tree, startLabel, endLabel):
        # divides tree into a list of basic blocks
        # we assume it has a Seq() at the top, and no other seqs or eseqs
        assert (isinstance(tree, ir.Seq))
        tree.children.append(ir.Label(endLabel, tree.node))

        blocks = []
        label = startLabel
        inBlock = 0
        block = []
        for stm in tree.children:
            if isinstance(stm, ir.Label):
                if block == []:
                    block.append(stm)
                else:
                    # close existing block, create a new one
                    if not self.is_jump(block[-1]):
                        # append a jump to current label
                        block.append(ir.Jump(stm.name, stm.node))
                    blocks.append(block)
                    block = [stm]
            else:
                if block == []:
                    # manufacture a label if first stm is not a label
                    block.append(ir.Label(label, tree.node))
                    label = self.symbols.newLabel()
                block.append(stm)
                if self.is_jump(stm):
                    blocks.append(block)
                    block = []
        return blocks
예제 #4
0
 def visit_while_statement(self, node, *args):
     lbl_start = self.get_id()
     lbl_body = self.get_id()
     lbl_end = self.get_id()
     return [
         ir.Label(lbl_start),
         self.visit(node.condition, ir.COND, lbl_body, lbl_end),
         ir.Label(lbl_body),
         list(map(self.visit, node.stmt)),
         ir.Jump(lbl_start),
         ir.Label(lbl_end),
     ]
예제 #5
0
 def visit_if_statement(self, node, *args):
     lbl_then = self.get_id()
     lbl_else = self.get_id()
     lbl_end = self.get_id()
     return [
         self.visit(node.condition, ir.COND, lbl_then, lbl_else),
         ir.Label(lbl_then),
         list(map(self.visit, node.stmt_then)),
         ir.Jump(lbl_end),
         ir.Label(lbl_else),
         list(map(self.visit, node.stmt_else)),
         ir.Label(lbl_end),
     ]
예제 #6
0
 def visit_bin_op(self, node, target, *args):
     if node.op in ['+', '-', '*', '%'] or (node.op == '<'
                                            and target == ir.EXPR):
         assert target == ir.EXPR
         lhs = self.get_id()
         rhs = self.get_id()
         arg1, arg2 = self.reorder_for_bin_op(node.left, node.right, lhs,
                                              rhs)
         return [
             arg1,
             arg2,
             ir.BinOp(node.op, lhs, rhs, args[0]),
         ]
     if node.op == '<':
         assert target == ir.COND
         lhs = self.get_id()
         rhs = self.get_id()
         arg1, arg2 = self.reorder_for_bin_op(node.left, node.right, lhs,
                                              rhs)
         return [
             arg1,
             arg2,
             ir.CJumpLess(lhs, rhs, args[0], args[1]),
         ]
     if node.op == '&&':
         if target == ir.COND:
             lbl_second_arg = self.get_id()
             return [
                 self.visit(node.left, ir.COND, lbl_second_arg, args[1]),
                 ir.Label(lbl_second_arg),
                 self.visit(node.right, ir.COND, args[0], args[1]),
             ]
         else:
             lbl_second_arg = self.get_id()
             lbl_false = self.get_id()
             lbl_true = self.get_id()
             lbl_end = self.get_id()
             return [
                 self.visit(node.left, ir.COND, lbl_second_arg, lbl_false),
                 ir.Label(lbl_second_arg),
                 self.visit(node.right, ir.COND, lbl_true, lbl_false),
                 ir.Label(lbl_true),
                 ir.Const(1, args[0]),
                 ir.Jump(lbl_end),
                 ir.Label(lbl_false),
                 ir.Const(0, args[0]),
                 ir.Label(lbl_end),
             ]
     if node.op == '||':
         if target == ir.COND:
             lbl_second_arg = self.get_id()
             return [
                 self.visit(node.left, ir.COND, args[0], lbl_second_arg),
                 ir.Label(lbl_second_arg),
                 self.visit(node.right, ir.COND, args[0], args[1]),
             ]
         else:
             lbl_second_arg = self.get_id()
             lbl_false = self.get_id()
             lbl_true = self.get_id()
             lbl_end = self.get_id()
             return [
                 self.visit(node.left, ir.COND, lbl_true, lbl_second_arg),
                 ir.Label(lbl_second_arg),
                 self.visit(node.right, ir.COND, lbl_true, lbl_false),
                 ir.Label(lbl_false),
                 ir.Const(0, args[0]),
                 ir.Jump(lbl_end),
                 ir.Label(lbl_true),
                 ir.Const(1, args[0]),
                 ir.Label(lbl_end),
             ]
     assert False
예제 #7
0
 def jump(self, dest):
     return ir.Jump(dest, self.fakeNode)