# 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
                if self.underestimate:
                    info[self.node_prop_out] = set()
                elif self.g.props.get("noreturn") or self.g.props.get("name") == "main":
                    info[self.node_prop_out] = set()
                else:
                    rets = progdb.FUNC_DB.get(self.g.props.get("name"), {}).get("returns")
                    if rets is not None:
                        assert isinstance(rets, set)
                        info[self.node_prop_out] = rets
                    elif "modifieds" in self.g.props:
                        info[self.node_prop_out] = self.g.props["modifieds"]
                        log.warning("Conservatively using modifieds as function live-out")
                    elif "reach_exit" in self.g.props:
                        info[self.node_prop_out] = self.g.props["reach_exit"]
                        log.warning("Conservatively using reach_exit as function live-out")
                    else:
                        info[self.node_prop_out] = set()
            else:
                info[self.node_prop_out] = set()

            bblock = info["val"]

            kill = set()
            gen = set()
            for inst in bblock.items:
                if inst.op == "call" and self.skip_calls:
                    continue

                # If we underestimate liveness, assume function
                # calls don't use anything, only kill liveness below.

# 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

                if self.underestimate:
                    info[self.node_prop_out] = set()
                elif self.g.props.get("noreturn") or self.g.props.get("name") == "main":
                    info[self.node_prop_out] = set()
                else:
                    rets = progdb.FUNC_DB.get(self.g.props.get("name"), {}).get("returns")
                    if rets is not None:
                        assert isinstance(rets, set)
                        info[self.node_prop_out] = rets
                    elif "modifieds" in self.g.props:
                        info[self.node_prop_out] = self.g.props["modifieds"]
                        log.warning("Conservatively using modifieds as function live-out")
                    elif "reach_exit" in self.g.props:
                        info[self.node_prop_out] = self.g.props["reach_exit"]
                        log.warning("Conservatively using reach_exit as function live-out")
                    else:
                        info[self.node_prop_out] = set()
            else:
                info[self.node_prop_out] = set()

            bblock = info["val"]

            kill = set()
            gen = set()
            for inst in bblock.items:
                if inst.op == "call" and self.skip_calls:
                    continue

                # If we underestimate liveness, assume function
                # calls don't use anything, only kill liveness below.

                if inst.op != "call" or not self.underestimate: