# Path: core.py
# def is_expr(e):
#     return isinstance(e, EXPR)
# 
# def is_mem(e):
#     return isinstance(e, MEM)
# 
# Path: utils.py
# def set_union(*sets):
#     # Python's set.union is unfortunately not a class method,
#     # but a normal method, [and if used as unbound method],
#     # requires at least one argument (set).
#     if sets:
#         return set.union(*sets)
#     return set()
# 
# def set_intersection(*sets):
#     # Python's set.intersection is unfortunately not a class method,
#     # but a normal method, [and if used as unbound method],
#     # requires at least one argument (set).
#     if sets:
#         return set.intersection(*sets)
#     return set()
# 
# Path: cfgutils.py
# def foreach_bblock(cfg, func, join_func=lambda a, b: a or b, **kwargs):
#     """Apply basic-block level transformation to each block in CFG.
#     Return cumulative status (OR of each block's status).
#     """
#     res = Ellipsis
#     for addr, info in cfg.iter_sorted_nodes():
#         bblock = info["val"]
#         r = func(bblock, **kwargs)
#         if res is Ellipsis:
#             res = r
#         else:
#             res = join_func(res, r)
#     return res


import logging
import core
                    import progdb
from core import is_expr, is_mem
from utils import set_union, set_intersection
from cfgutils import foreach_bblock
            all_defs = foreach_bblock(self.g, lambda b: b.def_addrs(self.regs_only), set.union)
        else:
            all_defs = foreach_bblock(self.g, lambda b: set((v, b.addr) for v in b.defs(self.regs_only)), set.union)

        for node, info in self.g.nodes_props():
            if node == entry:
                # Entry's in set to all vars, with "undefined" definition location (None).
                info[self.node_prop_in] = set(((v[0], None) for v in all_defs))
            else:
                info[self.node_prop_in] = set()
            info[self.node_prop_out] = set()

            bblock = info["val"]
            kill = set()
            gen = set()
            for inst in bblock.items:
                addr = inst.addr if self.inst_level else bblock.addr
                defs = inst.defs(self.regs_only)
                # Kill any real matching defs in function
                kill |= {x for x in all_defs if x[0] in defs}
                # and also any "undefined" defs from function reach-in
                kill |= {(r, None) for r in defs}
                for d in defs:
                    gen.add((d, addr))
            info[self.node_prop_kill] = kill
            info[self.node_prop_gen] = gen


class LiveVarAnalysis(GenKillAnalysis):
    forward = False

# Path: core.py
# def is_expr(e):
#     return isinstance(e, EXPR)
# 
# def is_mem(e):
#     return isinstance(e, MEM)
# 
# Path: utils.py
# def set_union(*sets):
#     # Python's set.union is unfortunately not a class method,
#     # but a normal method, [and if used as unbound method],
#     # requires at least one argument (set).
#     if sets:
#         return set.union(*sets)
#     return set()
# 
# def set_intersection(*sets):
#     # Python's set.intersection is unfortunately not a class method,
#     # but a normal method, [and if used as unbound method],
#     # requires at least one argument (set).
#     if sets:
#         return set.intersection(*sets)
#     return set()
# 
# Path: cfgutils.py
# def foreach_bblock(cfg, func, join_func=lambda a, b: a or b, **kwargs):
#     """Apply basic-block level transformation to each block in CFG.
#     Return cumulative status (OR of each block's status).
#     """
#     res = Ellipsis
#     for addr, info in cfg.iter_sorted_nodes():
#         bblock = info["val"]
#         r = func(bblock, **kwargs)
#         if res is Ellipsis:
#             res = r
#         else:
#             res = join_func(res, r)
#     return res


# Path: dataflow.py
import logging
import core
                    import progdb
from core import is_expr, is_mem
from utils import set_union, set_intersection
from cfgutils import foreach_bblock

            all_defs = foreach_bblock(self.g, lambda b: b.def_addrs(self.regs_only), set.union)
        else:
            all_defs = foreach_bblock(self.g, lambda b: set((v, b.addr) for v in b.defs(self.regs_only)), set.union)

        for node, info in self.g.nodes_props():
            if node == entry:
                # Entry's in set to all vars, with "undefined" definition location (None).
                info[self.node_prop_in] = set(((v[0], None) for v in all_defs))
            else:
                info[self.node_prop_in] = set()
            info[self.node_prop_out] = set()

            bblock = info["val"]
            kill = set()
            gen = set()
            for inst in bblock.items:
                addr = inst.addr if self.inst_level else bblock.addr
                defs = inst.defs(self.regs_only)
                # Kill any real matching defs in function
                kill |= {x for x in all_defs if x[0] in defs}
                # and also any "undefined" defs from function reach-in
                kill |= {(r, None) for r in defs}
                for d in defs:
                    gen.add((d, addr))
            info[self.node_prop_kill] = kill
            info[self.node_prop_gen] = gen


class LiveVarAnalysis(GenKillAnalysis):
    forward = False

    join_op = staticmethod(set_union)