def __init__(self, term): """Constructor for Term which converts term to appropriate form Args: term (Variable|Constant|string): Either an instantiated Variable or Constant, or a string to be passed to the appropriate constructor """ super(Term, self).__init__() is_var_or_const = isinstance(term, Variable) or isinstance(term, Constant) self.term = term if is_var_or_const else (Variable(term) if is_var(term) else Constant(term))
def unmark_live_variable_definitions(code, live_statements): statements = get_statements(code) worklist = [ls["statement"][x] for ls in live_statements for x in ls["statement"] if x.startswith("src") and is_var(ls["statement"][x])] while len(worklist): next_var = worklist.pop() for statement in statements: s = statement["statement"] statement_vars = [s[var] for var in s if var.startswith("src") and is_var(s[var])] if "dest" in s and s["dest"] == next_var and "delete" in s: del s["delete"] worklist.extend(statement_vars) live_statements.append(statement)
def bound_to(self, variable): """Check if variable is bound. If so return value bound to it, else False. Args: variable (Variable): variable to check for binding Returns: Variable|Constant|False: returns bound term if variable is bound else False """ if variable.element in self.bindings_dict.keys(): value = self.bindings_dict[variable.element] if value: return Variable(value) if is_var(value) else Constant(value) return False
def conditional_propagation(code): worklist = [] blocks = get_blocks(code) global variables variables = get_variables(code) for v in variables: # Variables with no definition must be input to the program if variables[v].has_key("def_site"): variables[v]["evidence"] = "never" else: variables[v]["evidence"] = "over" for block in code["blocks"]: block["delete"] = True #Entry block is always executable if block["name"] == code["starting_block"][0]: add_block_to_worklist(block, worklist) block["delete"] = False branch = "nil" while len(worklist): s = worklist.pop(0) # Executable Blocks with only 1 successor, that block must also be executable if len(get_block(s, code, blocks)["next_block"]) >= 1: if get_next_block(code, blocks, s, 0)["delete"] and len(get_block(s, code, blocks)["next_block"]) == 1: get_next_block(code, blocks, s, 0)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 0), worklist) if "dest" in s: #any overloaded variable cannot chance state if variables[s["dest"]]["evidence"] != "over": #Any executable statement v := x op y with x and y constant and exectuable , set v to constant x op y #Any executable statement v := x op y with x or y is overloaded and exectuable, set v overloaded if is_executable (code, s["src1"], variables): if s["op"] == "MOV": if is_constant_val(s["src1"], variables): if get_value (variables, s["dest"]) == "never": variables [s["dest"]]["evidence"] = get_value (variables, s["src1"]) update_worklist(code, worklist, s) elif get_value (variables, s["dest"]) != get_value (variables, s["dest"]): variables [s["dest"]]["evidence"] = "over" update_worklist(code, worklist, s) else: variables [s["dest"]]["evidence"] = "over" update_worklist(code, worklist, s) if s["op"] in FOLDABLE_OPS: if is_executable (code, s["src2"], variables): if is_constant_val(s["src1"], variables) and is_constant_val(s["src2"], variables): try: val1 = int(get_value(variables, s["src1"])[1:]) val2 = int(get_value(variables, s["src2"])[1:]) except ValueError: return const = "#" + str(_do_op(s["op"], val1, val2)) if get_value (variables, s["dest"]) == "never": variables [s["dest"]]["evidence"] = const update_worklist(code, worklist, s) elif get_value (variables, s["dest"]) != const: variables [s["dest"]]["evidence"] = "over" update_worklist(code, worklist, s) else: variables [s["dest"]]["evidence"] = "over" update_worklist(code, worklist, s) # If v assigned from phi op, and if all srcs that are constant and executable are the same and there are no variables that have seen evidence of use, assign constant value to v. # If v assigned from phi op, and at least 2 srcs are different constants and are executable, v is a overloaded # If v assigned from phi op, and at least 1 srcs is overloaded and is executable, v is overloaded if s["op"] == "phi": operands = [s[x] for x in s if x.startswith("src")] for o in operands: if is_executable (code, o, variables): if is_constant_val(o, variables): if get_value (variables, s["dest"]) == "never": variables [s["dest"]]["evidence"] = get_value (variables, o) update_worklist(code, worklist, s) elif get_value (variables, s["dest"]) != get_value (variables, o): variables [s["dest"]]["evidence"] = "over" update_worklist(code, worklist, s) else: variables [s["dest"]]["evidence"] = "over" update_worklist(code, worklist, s) # If value loaded from memory, evidence of overloading if s["op"] in MEMORY_OPS: variables[s["dest"]]["evidence"] = "over" update_worklist(code, worklist, s) if s["op"] == "CMP": # if branch instruction, if either src is a overloaded, then both paths may be executed and should be added to the worklist to be marked as such and their statements analysed. if is_var(s["src1"], variables) or is_var(s["src2"], variables): add_block_to_worklist(get_next_block(code, blocks, s, 0) , worklist) get_next_block(code, blocks, s, 0)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 1) , worklist) get_next_block(code, blocks, s, 1)["delete"] = False #If a branch and both srcs are constant, add appropriate path to work path. else: val1 = int(get_value(variables,s["src1"])[1:]) val2 = int(get_value(variables,s["src2"])[1:]) if val1 > val2 : branch = "gt" elif val1 < val2 : branch = "lt" else: branch = "eq" #Note - these do not take in to account all possible instructions in the arm instruction set, such as any operation being conditional if branch != "nil": if s["op"] == "BEQ": if branch == "eq": get_next_block(code, blocks, s, 0)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 0) , worklist) else: get_next_block(code, blocks, s, 1)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 1) , worklist) if s["op"] == "BNE": if branch != "eq": get_next_block(code, blocks, s, 0)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 0) , worklist) else: get_next_block(code, blocks, s, 1)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 1) , worklist) if s["op"] == "BLT": if branch == "lt": get_next_block(code, blocks, s, 0)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 0) , worklist) else: get_next_block(code, blocks, s, 1)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 1) , worklist) if s["op"] == "BLE": if branch == "eq" or branch == "lt" : get_next_block(code, blocks, s, 0)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 0) , worklist) else: get_next_block(code, blocks, s, 1)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 1) , worklist) if s["op"] == "BGT": if branch == "gt": get_next_block(code, blocks, s, 0)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 0) , worklist) else: get_next_block(code, blocks, s, 1)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 1) , worklist) if s["op"] == "BGE": if branch == "eq" or branch == "gt" : get_next_block(code, blocks, s, 0)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 0) , worklist) else: get_next_block(code, blocks, s, 1)["delete"] = False add_block_to_worklist(get_next_block(code, blocks, s, 1) , worklist) # Delete any block that is not executed for block in code["blocks"]: i = 0 #delete references to deleted blocks while i < len(block["next_block"]): if code["blocks"][blocks[block["next_block"][i]]]["delete"]: del block["next_block"][i] else: i += 1 for block in code["blocks"]: if not block["delete"]: del block["delete"] i = 0 while i < len(code["blocks"]): if "delete" in code["blocks"][i]: del code["blocks"][i] else: i += 1 worklistfix = [] for block in code["blocks"]: for statement in block["code"]: worklistfix.append(statement) while len(worklistfix): s = worklistfix.pop(0) #propogate constants if "dest" in s: if variables[s["dest"]]["evidence"].startswith('#'): _propagate_constant(code, s, variables[s["dest"]]["evidence"]) #remove any branch ops that are constant if s["op"] == "CMP": if is_constant_val(s["src1"], variables) and is_constant_val(s["src2"], variables): remove_statement(code, s) if s["op"] in CONDITIONAL_BRANCH: block = get_block(s, code, blocks)["code"] if not any(statement["op"] == "CMP" for statement in block): remove_statement(code, s) if s["block"]: del s["block"]