# Path: androguard/decompiler/dad/instruction.py
# class Variable(IRForm):
#     def __init__(self, value):
#         self.v = value
#         self.declared = False
#         self.type = None
#         self.name = value
# 
#     def get_used_vars(self):
#         return [self.v]
# 
#     def is_ident(self):
#         return True
# 
#     def value(self):
#         return self.v
# 
#     def visit(self, visitor):
#         return visitor.visit_variable(self)
# 
#     def visit_decl(self, visitor):
#         return visitor.visit_decl(self)
# 
#     def __str__(self):
#         return 'VAR_%s' % self.name
# 
# class ThisParam(Param):
#     def __init__(self, value, atype):
#         super().__init__(value, atype)
#         self.this = True
#         self.super = False
# 
#     def visit(self, visitor):
#         if self.super:
#             return visitor.visit_super()
#         return visitor.visit_this()
# 
#     def __str__(self):
#         return 'THIS'
# 
# class Param(Variable):
#     def __init__(self, value, atype):
#         super().__init__(value)
#         self.declared = True
#         self.type = atype
#         self.this = False
# 
#     def is_const(self):
#         return True
# 
#     def visit(self, visitor):
#         return visitor.visit_param(self.v, data=self.type)
# 
#     def __str__(self):
#         return 'PARAM_%s' % self.name
# 
# Path: androguard/decompiler/dad/util.py
# def build_path(graph, node1, node2, path=None):
#     """
#     Build the path from node1 to node2.
#     The path is composed of all the nodes between node1 and node2,
#     node1 excluded. Although if there is a loop starting from node1, it will be
#     included in the path.
#     """
#     if path is None:
#         path = []
#     if node1 is node2:
#         return path
#     path.append(node2)
#     for pred in graph.all_preds(node2):
#         if pred in path:
#             continue
#         build_path(graph, node1, pred, path)
#     return path
# 
# def common_dom(idom, cur, pred):
#     if not (cur and pred):
#         return cur or pred
#     while cur is not pred:
#         while cur.num < pred.num:
#             pred = idom[pred]
#         while cur.num > pred.num:
#             cur = idom[cur]
#     return cur
# 
# Path: androguard/decompiler/dad/node.py
# class Node:
#     def __init__(self, name):
#         self.name = name
#         self.num = 0
#         self.follow = {'if': None, 'loop': None, 'switch': None}
#         self.looptype = LoopType()
#         self.type = NodeType()
#         self.in_catch = False
#         self.interval = None
#         self.startloop = False
#         self.latch = None
#         self.loop_nodes = []
# 
#     def copy_from(self, node):
#         self.num = node.num
#         self.looptype = node.looptype.copy()
#         self.interval = node.interval
#         self.startloop = node.startloop
#         self.type = node.type.copy()
#         self.follow = node.follow.copy()
#         self.latch = node.latch
#         self.loop_nodes = node.loop_nodes
#         self.in_catch = node.in_catch
# 
#     def update_attribute_with(self, n_map):
#         self.latch = n_map.get(self.latch, self.latch)
#         for follow_type, value in self.follow.items():
#             self.follow[follow_type] = n_map.get(value, value)
#         self.loop_nodes = list({n_map.get(n, n) for n in self.loop_nodes})
# 
#     def get_head(self):
#         return self
# 
#     def get_end(self):
#         return self
# 
#     def __repr__(self):
#         return '%s' % self


import logging
from collections import defaultdict
from androguard.decompiler.dad.instruction import (Variable, ThisParam, Param)
from androguard.decompiler.dad.util import build_path, common_dom
from androguard.decompiler.dad.node import Node
                    self.def_to_loc[kill].add(i)
            for defs, values in self.defs[node].items():
                self.DB[node].add(max(values))

    def run(self):
        nodes = list(self.g.rpo)
        while nodes:
            node = nodes.pop(0)
            newR = set()
            for pred in self.g.all_preds(node):
                newR.update(self.A[pred])
            if newR and newR != self.R[node]:
                self.R[node] = newR
                for suc in self.g.all_sucs(node):
                    if suc not in nodes:
                        nodes.append(suc)

            killed_locs = set()
            for reg in self.defs[node]:
                killed_locs.update(self.def_to_loc[reg])

            A = set()
            for loc in self.R[node]:
                if loc not in killed_locs:
                    A.add(loc)
            newA = A.union(self.DB[node])
            if newA != self.A[node]:
                self.A[node] = newA
                for suc in self.g.all_sucs(node):
                    if suc not in nodes:

# Path: androguard/decompiler/dad/instruction.py
# class Variable(IRForm):
#     def __init__(self, value):
#         self.v = value
#         self.declared = False
#         self.type = None
#         self.name = value
# 
#     def get_used_vars(self):
#         return [self.v]
# 
#     def is_ident(self):
#         return True
# 
#     def value(self):
#         return self.v
# 
#     def visit(self, visitor):
#         return visitor.visit_variable(self)
# 
#     def visit_decl(self, visitor):
#         return visitor.visit_decl(self)
# 
#     def __str__(self):
#         return 'VAR_%s' % self.name
# 
# class ThisParam(Param):
#     def __init__(self, value, atype):
#         super().__init__(value, atype)
#         self.this = True
#         self.super = False
# 
#     def visit(self, visitor):
#         if self.super:
#             return visitor.visit_super()
#         return visitor.visit_this()
# 
#     def __str__(self):
#         return 'THIS'
# 
# class Param(Variable):
#     def __init__(self, value, atype):
#         super().__init__(value)
#         self.declared = True
#         self.type = atype
#         self.this = False
# 
#     def is_const(self):
#         return True
# 
#     def visit(self, visitor):
#         return visitor.visit_param(self.v, data=self.type)
# 
#     def __str__(self):
#         return 'PARAM_%s' % self.name
# 
# Path: androguard/decompiler/dad/util.py
# def build_path(graph, node1, node2, path=None):
#     """
#     Build the path from node1 to node2.
#     The path is composed of all the nodes between node1 and node2,
#     node1 excluded. Although if there is a loop starting from node1, it will be
#     included in the path.
#     """
#     if path is None:
#         path = []
#     if node1 is node2:
#         return path
#     path.append(node2)
#     for pred in graph.all_preds(node2):
#         if pred in path:
#             continue
#         build_path(graph, node1, pred, path)
#     return path
# 
# def common_dom(idom, cur, pred):
#     if not (cur and pred):
#         return cur or pred
#     while cur is not pred:
#         while cur.num < pred.num:
#             pred = idom[pred]
#         while cur.num > pred.num:
#             cur = idom[cur]
#     return cur
# 
# Path: androguard/decompiler/dad/node.py
# class Node:
#     def __init__(self, name):
#         self.name = name
#         self.num = 0
#         self.follow = {'if': None, 'loop': None, 'switch': None}
#         self.looptype = LoopType()
#         self.type = NodeType()
#         self.in_catch = False
#         self.interval = None
#         self.startloop = False
#         self.latch = None
#         self.loop_nodes = []
# 
#     def copy_from(self, node):
#         self.num = node.num
#         self.looptype = node.looptype.copy()
#         self.interval = node.interval
#         self.startloop = node.startloop
#         self.type = node.type.copy()
#         self.follow = node.follow.copy()
#         self.latch = node.latch
#         self.loop_nodes = node.loop_nodes
#         self.in_catch = node.in_catch
# 
#     def update_attribute_with(self, n_map):
#         self.latch = n_map.get(self.latch, self.latch)
#         for follow_type, value in self.follow.items():
#             self.follow[follow_type] = n_map.get(value, value)
#         self.loop_nodes = list({n_map.get(n, n) for n in self.loop_nodes})
# 
#     def get_head(self):
#         return self
# 
#     def get_end(self):
#         return self
# 
#     def __repr__(self):
#         return '%s' % self


# Path: androguard/decompiler/dad/dataflow.py
import logging
from collections import defaultdict
from androguard.decompiler.dad.instruction import (Variable, ThisParam, Param)
from androguard.decompiler.dad.util import build_path, common_dom
from androguard.decompiler.dad.node import Node

                    self.def_to_loc[kill].add(i)
            for defs, values in self.defs[node].items():
                self.DB[node].add(max(values))

    def run(self):
        nodes = list(self.g.rpo)
        while nodes:
            node = nodes.pop(0)
            newR = set()
            for pred in self.g.all_preds(node):
                newR.update(self.A[pred])
            if newR and newR != self.R[node]:
                self.R[node] = newR
                for suc in self.g.all_sucs(node):
                    if suc not in nodes:
                        nodes.append(suc)

            killed_locs = set()
            for reg in self.defs[node]:
                killed_locs.update(self.def_to_loc[reg])

            A = set()
            for loc in self.R[node]:
                if loc not in killed_locs:
                    A.add(loc)
            newA = A.union(self.DB[node])
            if newA != self.A[node]:
                self.A[node] = newA
                for suc in self.g.all_sucs(node):
                    if suc not in nodes:

                        nodes.append(suc)