def op_FOR_ITER(self, inst, iterator, indval, pred): """ Assign new block other this instruction. """ assert inst.offset in self.blocks, "FOR_ITER must be block head" # Mark this block as the loop condition loop = self.syntax_blocks[-1] loop.condition = self.current_block_offset # Emit code val = self.get(iterator) iternext = ir.Expr.iternext(value=val, loc=self.loc) self.store(iternext, indval) itervalid = ir.Expr.itervalid(value=val, loc=self.loc) self.store(itervalid, pred) # Conditional jump br = ir.Branch(cond=self.get(pred), truebr=inst.next, falsebr=inst.get_jump_target(), loc=self.loc) self.current_block.append(br) # Add event listener to mark the following blocks as loop body def mark_as_body(offset, block): loop.body.append(offset) self._block_actions[loop] = mark_as_body
def mk_loop_header(typemap, phi_var, calltypes, scope, loc): """make a block that is a loop header updating iteration variables. target labels in branch need to be set. """ # iternext_var = iternext(phi_var) iternext_var = ir.Var(scope, mk_unique_var("$iternext_var"), loc) typemap[iternext_var.name] = types.containers.Pair( types.intp, types.boolean) iternext_call = ir.Expr.iternext(phi_var, loc) calltypes[iternext_call] = signature( types.containers.Pair( types.intp, types.boolean), types.range_iter64_type) iternext_assign = ir.Assign(iternext_call, iternext_var, loc) # pair_first_var = pair_first(iternext_var) pair_first_var = ir.Var(scope, mk_unique_var("$pair_first_var"), loc) typemap[pair_first_var.name] = types.intp pair_first_call = ir.Expr.pair_first(iternext_var, loc) pair_first_assign = ir.Assign(pair_first_call, pair_first_var, loc) # pair_second_var = pair_second(iternext_var) pair_second_var = ir.Var(scope, mk_unique_var("$pair_second_var"), loc) typemap[pair_second_var.name] = types.boolean pair_second_call = ir.Expr.pair_second(iternext_var, loc) pair_second_assign = ir.Assign(pair_second_call, pair_second_var, loc) # phi_b_var = pair_first_var phi_b_var = ir.Var(scope, mk_unique_var("$phi"), loc) typemap[phi_b_var.name] = types.intp phi_b_assign = ir.Assign(pair_first_var, phi_b_var, loc) # branch pair_second_var body_block out_block branch = ir.Branch(pair_second_var, -1, -1, loc) header_block = ir.Block(scope, loc) header_block.body = [iternext_assign, pair_first_assign, pair_second_assign, phi_b_assign, branch] return header_block
def _op_JUMP_IF(self, inst, pred, iftrue): brs = { True: inst.get_jump_target(), False: inst.next, } truebr = brs[iftrue] falsebr = brs[not iftrue] bra = ir.Branch(cond=self.get(pred), truebr=truebr, falsebr=falsebr, loc=self.loc) self.current_block.append(bra)
def test_branch(self): a = ir.Branch(self.var_a, 1, 2, self.loc1) b = ir.Branch(self.var_a, 1, 2, self.loc1) c = ir.Branch(self.var_a, 1, 2, self.loc2) d = ir.Branch(self.var_b, 1, 2, self.loc1) e = ir.Branch(self.var_a, 2, 2, self.loc1) f = ir.Branch(self.var_a, 1, 3, self.loc1) self.check(a, same=[b, c], different=[d, e, f])
def replace_target(term, src, dst): def replace(target): return (dst if target == src else target) if isinstance(term, ir.Branch): return ir.Branch(cond=term.cond, truebr=replace(term.truebr), falsebr=replace(term.falsebr), loc=term.loc) elif isinstance(term, ir.Jump): return ir.Jump(target=replace(term.target), loc=term.loc) else: assert not term.get_targets() return term
def _op_JUMP_IF(self, inst, pred, iftrue): brs = { True: inst.get_jump_target(), False: inst.next, } truebr = brs[iftrue] falsebr = brs[not iftrue] bra = ir.Branch(cond=self.get(pred), truebr=truebr, falsebr=falsebr, loc=self.loc) self.current_block.append(bra) # In a while loop? self._determine_while_condition((truebr, falsebr))
def op_FOR_ITER(self, inst, iterator, pair, indval, pred): """ Assign new block other this instruction. """ assert inst.offset in self.blocks, "FOR_ITER must be block head" # Emit code val = self.get(iterator) pairval = ir.Expr.iternext(value=val, loc=self.loc) self.store(pairval, pair) iternext = ir.Expr.pair_first(value=self.get(pair), loc=self.loc) self.store(iternext, indval) isvalid = ir.Expr.pair_second(value=self.get(pair), loc=self.loc) self.store(isvalid, pred) # Conditional jump br = ir.Branch(cond=self.get(pred), truebr=inst.next, falsebr=inst.get_jump_target(), loc=self.loc) self.current_block.append(br)