Beispiel #1
0
    def gen_return(self, builder: 'IRBuilder', value: Value,
                   line: int) -> None:
        if self.ret_reg is None:
            self.ret_reg = builder.alloc_temp(builder.ret_types[-1])

        builder.add(Assign(self.ret_reg, value))
        builder.add(Goto(self.target))
Beispiel #2
0
 def add_leave(self) -> Optional[Goto]:
     if not self.blocks[-1][-1].ops or not isinstance(
             self.blocks[-1][-1].ops[-1], Return):
         leave = Goto(INVALID_LABEL)
         self.add(leave)
         return leave
     return None
Beispiel #3
0
def add_block(ops: Iterable[Op], blocks: List[BasicBlock],
              label: Label) -> Label:
    block = BasicBlock(Label(len(blocks)))
    block.ops.extend(ops)
    block.ops.append(Goto(label))
    blocks.append(block)
    return block.label
Beispiel #4
0
    def visit_while_stmt(self, s: WhileStmt) -> Register:
        self.push_loop_stack()

        # Split block so that we get a handle to the top of the loop.
        goto = Goto(INVALID_LABEL)
        self.add(goto)
        top = self.new_block()
        goto.label = top.label
        branches = self.process_conditional(s.expr)

        body = self.new_block()
        # Bind "true" branches to the body block.
        self.set_branches(branches, True, body)
        s.body.accept(self)
        # Add branch to the top at the end of the body.
        self.add(Goto(top.label))
        next = self.new_block()
        # Bind "false" branches to the new block.
        self.set_branches(branches, False, next)

        self.pop_loop_stack(top, next)
        return INVALID_REGISTER
Beispiel #5
0
def add_block(decincs: DecIncs, cache: BlockCache, blocks: List[BasicBlock],
              label: BasicBlock) -> BasicBlock:
    decs, incs = decincs
    if not decs and not incs:
        return label

    # TODO: be able to share *partial* results
    if (label, decincs) in cache:
        return cache[label, decincs]

    block = BasicBlock()
    blocks.append(block)
    block.ops.extend(DecRef(reg, is_xdec=xdec) for reg, xdec in decs)
    block.ops.extend(IncRef(reg) for reg in incs)
    block.ops.append(Goto(label))
    cache[label, decincs] = block
    return block
Beispiel #6
0
    def visit_conditional_expr(self, expr: ConditionalExpr) -> Register:
        branches = self.process_conditional(expr.cond)
        target = self.alloc_target(self.node_type(expr))

        if_body = self.new_block()
        self.set_branches(branches, True, if_body)
        self.accept(expr.if_expr, target=target)
        if_goto_next = Goto(INVALID_LABEL)
        self.add(if_goto_next)

        else_body = self.new_block()
        self.set_branches(branches, False, else_body)
        self.accept(expr.else_expr, target=target)
        else_goto_next = Goto(INVALID_LABEL)
        self.add(else_goto_next)

        next = self.new_block()
        if_goto_next.label = next.label
        else_goto_next.label = next.label

        return target
Beispiel #7
0
 def test_goto(self) -> None:
     self.assert_emit(Goto(BasicBlock(2)), "goto CPyL2;")
Beispiel #8
0
 def goto(self, target: BasicBlock) -> None:
     if not self.blocks[-1].terminated:
         self.add(Goto(target))
Beispiel #9
0
 def goto(self, target: BasicBlock) -> None:
     if not self.blocks[-1][-1].ops or not isinstance(self.blocks[-1][-1].ops[-1], ControlOp):
         self.add(Goto(target))
Beispiel #10
0
 def gen_continue(self, builder: 'IRBuilder', line: int) -> None:
     builder.add(Goto(self.continue_block))
Beispiel #11
0
 def gen_break(self, builder: 'IRBuilder', line: int) -> None:
     builder.add(Goto(self.break_block))
Beispiel #12
0
 def goto_new_block(self) -> BasicBlock:
     goto = Goto(INVALID_LABEL)
     self.add(goto)
     block = self.new_block()
     goto.label = block.label
     return block
Beispiel #13
0
 def visit_continue_stmt(self, node: ContinueStmt) -> Register:
     self.continue_gotos[-1].append(Goto(INVALID_LABEL))
     self.add(self.continue_gotos[-1][-1])
     return INVALID_REGISTER
Beispiel #14
0
 def visit_break_stmt(self, node: BreakStmt) -> Register:
     self.break_gotos[-1].append(Goto(INVALID_LABEL))
     self.add(self.break_gotos[-1][-1])
     return INVALID_REGISTER
Beispiel #15
0
    def visit_for_stmt(self, s: ForStmt) -> Register:
        if (isinstance(s.expr, CallExpr)
                and isinstance(s.expr.callee, RefExpr)
                and s.expr.callee.fullname == 'builtins.range'):
            self.push_loop_stack()

            # Special case for x in range(...)
            # TODO: Check argument counts and kinds; check the lvalue
            end = s.expr.args[0]
            end_reg = self.accept(end)

            # Initialize loop index to 0.
            index_reg = self.assign(s.index,
                                    IntExpr(0),
                                    IntRType(),
                                    IntRType(),
                                    declare_new=True)
            goto = Goto(INVALID_LABEL)
            self.add(goto)

            # Add loop condition check.
            top = self.new_block()
            goto.label = top.label
            branch = Branch(index_reg, end_reg, INVALID_LABEL, INVALID_LABEL,
                            Branch.INT_LT)
            self.add(branch)
            branches = [branch]

            body = self.new_block()
            self.set_branches(branches, True, body)
            s.body.accept(self)

            end_goto = Goto(INVALID_LABEL)
            self.add(end_goto)
            end_block = self.new_block()
            end_goto.label = end_block.label

            # Increment index register.
            one_reg = self.alloc_temp(IntRType())
            self.add(LoadInt(one_reg, 1))
            self.add(
                PrimitiveOp(index_reg, PrimitiveOp.INT_ADD, index_reg,
                            one_reg))

            # Go back to loop condition check.
            self.add(Goto(top.label))
            next = self.new_block()
            self.set_branches(branches, False, next)

            self.pop_loop_stack(end_block, next)
            return INVALID_REGISTER

        if self.node_type(s.expr).name == 'list':
            self.push_loop_stack()

            expr_reg = self.accept(s.expr)

            index_reg = self.alloc_temp(IntRType())
            self.add(LoadInt(index_reg, 0))

            one_reg = self.alloc_temp(IntRType())
            self.add(LoadInt(one_reg, 1))

            assert isinstance(s.index, NameExpr)
            assert isinstance(s.index.node, Var)
            lvalue_reg = self.environment.add_local(s.index.node,
                                                    self.node_type(s.index))

            condition_block = self.goto_new_block()

            # For compatibility with python semantics we recalculate the length
            # at every iteration.
            len_reg = self.alloc_temp(IntRType())
            self.add(PrimitiveOp(len_reg, PrimitiveOp.LIST_LEN, expr_reg))

            branch = Branch(index_reg, len_reg, INVALID_LABEL, INVALID_LABEL,
                            Branch.INT_LT)
            self.add(branch)
            branches = [branch]

            body_block = self.new_block()
            self.set_branches(branches, True, body_block)

            target_list_type = self.types[s.expr]
            assert isinstance(target_list_type, Instance)
            target_type = self.type_to_rtype(target_list_type.args[0])
            value_box = self.alloc_temp(ObjectRType())
            self.add(
                PrimitiveOp(value_box, PrimitiveOp.LIST_GET, expr_reg,
                            index_reg))

            self.unbox_or_cast(value_box, target_type, target=lvalue_reg)

            s.body.accept(self)

            end_block = self.goto_new_block()
            self.add(
                PrimitiveOp(index_reg, PrimitiveOp.INT_ADD, index_reg,
                            one_reg))
            self.add(Goto(condition_block.label))

            next_block = self.new_block()
            self.set_branches(branches, False, next_block)

            self.pop_loop_stack(end_block, next_block)

            return INVALID_REGISTER

        assert False, 'for not supported'
Beispiel #16
0
 def test_goto(self) -> None:
     self.assert_emit(Goto(Label(2)), "goto CPyL2;")