def SSI_to_SSA(graph): """Rename the variables in a flow graph as much as possible without violating the SSA rule. 'SSI' means that each Variable in a flow graph is defined only once in the whole graph; all our graphs are SSI. This function does not break that rule, but changes the 'name' of some Variables to give them the same 'name' as other Variables. The result looks like an SSA graph. 'SSA' means that each var name appears as the result of an operation only once in the whole graph, but it can be passed to other blocks across links. """ variable_families = DataFlowFamilyBuilder(graph).get_variable_families() # rename variables to give them the name of their familiy representant for v in variable_families.keys(): v1 = variable_families.find_rep(v) if v1 != v: v.set_name_from(v1) # sanity-check that the same name is never used several times in a block variables_by_name = {} for block in flatten(graph): if not isinstance(block, Block): continue vars = [op.result for op in block.operations] for link in block.exits: vars += link.getextravars() assert len(dict.fromkeys([ v.name for v in vars ])) == len(vars), ("duplicate variable name in %r" % (block, )) for v in vars: variables_by_name.setdefault(v.name, []).append(v) # sanity-check that variables with the same name have the same concretetype for vname, vlist in variables_by_name.items(): vct = [getattr(v, 'concretetype', None) for v in vlist] assert vct == vct[:1] * len(vct), ( "variables called %s have mixed concretetypes: %r" % (vname, vct))
def SSI_to_SSA(graph): """Rename the variables in a flow graph as much as possible without violating the SSA rule. 'SSI' means that each Variable in a flow graph is defined only once in the whole graph; all our graphs are SSI. This function does not break that rule, but changes the 'name' of some Variables to give them the same 'name' as other Variables. The result looks like an SSA graph. 'SSA' means that each var name appears as the result of an operation only once in the whole graph, but it can be passed to other blocks across links. """ variable_families = DataFlowFamilyBuilder(graph).get_variable_families() # rename variables to give them the name of their familiy representant for v in variable_families.keys(): v1 = variable_families.find_rep(v) if v1 != v: v.set_name_from(v1) # sanity-check that the same name is never used several times in a block variables_by_name = {} for block in flatten(graph): if not isinstance(block, Block): continue vars = [op.result for op in block.operations] for link in block.exits: vars += link.getextravars() assert len(dict.fromkeys([v.name for v in vars])) == len(vars), ( "duplicate variable name in %r" % (block,)) for v in vars: variables_by_name.setdefault(v.name, []).append(v) # sanity-check that variables with the same name have the same concretetype for vname, vlist in variables_by_name.items(): vct = [getattr(v, 'concretetype', None) for v in vlist] assert vct == vct[:1] * len(vct), ( "variables called %s have mixed concretetypes: %r" % (vname, vct))
def check_malloc_removed(cls, graph, expected_mallocs, expected_calls): count_mallocs = 0 count_calls = 0 for node in flatten(graph): if isinstance(node, Block): for op in node.operations: if op.opname == 'malloc': count_mallocs += 1 if op.opname == 'direct_call': count_calls += 1 assert count_mallocs == expected_mallocs assert count_calls == expected_calls
def check_malloc_removed(cls, graph): remover = cls.MallocRemover() checkgraph(graph) count1 = count2 = 0 for node in flatten(graph): if isinstance(node, Block): for op in node.operations: if op.opname == cls.MallocRemover.MALLOC_OP: S = op.args[0].value if not remover.union_wrapper(S): # union wrappers are fine count1 += 1 if op.opname in ('direct_call', 'indirect_call'): count2 += 1 assert count1 == 0 # number of mallocs left assert count2 == 0 # number of calls left
def check_malloc_removed(cls, graph): remover = cls.MallocRemover() checkgraph(graph) count1 = count2 = 0 for node in flatten(graph): if isinstance(node, Block): for op in node.operations: if op.opname == cls.MallocRemover.MALLOC_OP: S = op.args[0].value if not remover.union_wrapper( S): # union wrappers are fine count1 += 1 if op.opname in ('direct_call', 'indirect_call'): count2 += 1 assert count1 == 0 # number of mallocs left assert count2 == 0 # number of calls left
def test_highly_branching_example(self): x = self.codetest(self.highly_branching_example) assert len(flatten(x)) < 60 # roughly 20 blocks + 30 links