Esempio n. 1
0
def after_branch_increfs(label: Label, pre_borrow: AnalysisDict,
                         source_borrowed: Set[Register],
                         env: Environment) -> List[Op]:
    target_borrowed = pre_borrow[label, 0]
    incref = source_borrowed - target_borrowed
    if incref:
        return [IncRef(reg, env.types[reg]) for reg in sorted(incref)]
    return []
Esempio n. 2
0
def transform_block(block: BasicBlock, pre_live: AnalysisDict[Register],
                    post_live: AnalysisDict[Register],
                    pre_borrow: AnalysisDict[Register],
                    env: Environment) -> None:
    old_ops = block.ops
    ops = []  # type: List[Op]
    for i, op in enumerate(old_ops):
        key = (block.label, i)
        if isinstance(op, (Assign, Cast, Box)):
            # These operations just copy/steal a reference and don't create new
            # references.
            if op.src in post_live[key] or op.src in pre_borrow[key]:
                ops.append(IncRef(op.src, env.types[op.src]))
                if (op.dest not in pre_borrow[key]
                        and op.dest in pre_live[key]):
                    ops.append(DecRef(op.dest, env.types[op.dest]))
            ops.append(op)
            if op.dest not in post_live[key]:
                ops.append(DecRef(op.dest, env.types[op.dest]))
        elif isinstance(op, RegisterOp):
            # These operations construct a new reference.
            tmp_reg = None  # type: Optional[Register]
            if (op.dest not in pre_borrow[key] and op.dest in pre_live[key]):
                if op.dest not in op.sources():
                    ops.append(DecRef(op.dest, env.types[op.dest]))
                else:
                    tmp_reg = env.add_temp(env.types[op.dest])
                    ops.append(Assign(tmp_reg, op.dest))
            ops.append(op)
            for src in op.unique_sources():
                # Decrement source that won't be live afterwards.
                if src not in post_live[key] and src not in pre_borrow[key]:
                    if src != op.dest:
                        ops.append(DecRef(src, env.types[src]))
            if op.dest is not None and op.dest not in post_live[key]:
                ops.append(DecRef(op.dest, env.types[op.dest]))
            if tmp_reg is not None:
                ops.append(DecRef(tmp_reg, env.types[tmp_reg]))
        elif isinstance(op, Return) and op.reg in pre_borrow[key]:
            # The return op returns a new reference.
            ops.append(IncRef(op.reg, env.types[op.reg]))
            ops.append(op)
        else:
            ops.append(op)
    block.ops = ops
Esempio n. 3
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
Esempio n. 4
0
 def test_inc_ref(self) -> None:
     self.assert_emit(IncRef(self.m), "CPyTagged_IncRef(cpy_r_m);")
Esempio n. 5
0
def maybe_append_inc_ref(ops: List[Op], dest: Value) -> None:
    if dest.type.is_refcounted:
        ops.append(IncRef(dest))