def clean_cfg(blocks): changed = True while changed: preds, succs = cfg.edges(blocks) visited = dict.fromkeys(blocks.keys(),False) changed = _clean_cfg(blocks.keys()[0], blocks, preds, succs, visited) # for block in blocks: # print('{}:'.format(block)) # print('{}:'.format(blocks[block])) return blocks
def br_removal(blocks): in_, out = df_worklist(blocks, ANALYSES['cprop']) # overwirte blocks preds, succs = cfg.edges(blocks) for index, block in blocks.items(): vals = out[index] if block[-1] is not None and block[-1]['op'] == 'br': guard = block[-1]['args'][0] if guard in vals: block[-1]['op'] = 'jmp' if vals[guard]: block[-1]['args'] = [block[-1]['args'][1]] else: block[-1]['args'] = [block[-1]['args'][2]] return blocks
def unreachable_removal(blocks): preds, succs = cfg.edges(blocks) reachable = dict.fromkeys(blocks.keys(),False) reachable[blocks.keys()[0]] = True stack = [blocks.keys()[0]] while(len(stack) != 0): b = stack.pop() for s in succs[b]: if not reachable[s]: reachable[s] = True stack.append(s) for b, r in reachable.items(): if not r : del blocks[b] return blocks
def cfg_to_code(blocks, f_name): preds, succs = cfg.edges(blocks) instrs = [] for name, block in blocks.items(): if len(instrs) != 0 and instrs[-1]['op'] == 'jmp' and instrs[-1][ 'args'][0] == name: instrs = instrs[:-1] if len(preds[name]) == 1: # this label is only for the fall through instrs += block continue if len(preds[name]) != 0: instrs += [{"label": name}] instrs += block data = {'functions': [{"name": f_name}]} data['functions'][0]['instrs'] = instrs json_data = json.dumps(data, indent=2, sort_keys=True) return json_data
def df_worklist(blocks, analysis): """The worklist algorithm for iterating a data flow analysis to a fixed point. """ preds, succs = cfg.edges(blocks) # Switch between directions. if analysis.forward: first_block = list(blocks.keys())[0] # Entry. in_edges = preds out_edges = succs else: first_block = list(blocks.keys())[-1] # Exit. in_edges = succs out_edges = preds # Initialize. in_ = {first_block: analysis.init} out = {node: analysis.init for node in blocks} # Iterate. worklist = list(blocks.keys()) while worklist: node = worklist.pop(0) inval = analysis.merge(out[n] for n in in_edges[node]) in_[node] = inval outval = analysis.transfer(blocks[node], inval) if outval != out[node]: out[node] = outval worklist += out_edges[node] if analysis.forward: return in_, out else: return out, in_
def df_worklist(blocks, bottom, join, transfer): preds, succs = cfg.edges(blocks) entry = list(blocks.keys())[0] # Initialize. invals = {entry: bottom} outvals = {node: bottom for node in blocks} worklist = list(blocks.keys()) # Iterate. while worklist: node = worklist.pop(0) inval = join(outvals[n] for n in preds[node]) invals[node] = inval outval = transfer(blocks[node], inval) if outval != outvals[node]: outvals[node] = outval worklist += succs[node] print(invals) print(outvals)
def tail_merging_once(blocks): preds, succs = cfg.edges(blocks) bns = list(blocks.keys()) for block in bns: count = {} # merge two preds for p in preds[block]: instr = blocks[p][-1] if instr is not None and instr['op'] == 'jmp': k = canonicalize(instr) if k not in count: count[k] = p else: # find two blocks can be merged b1 = blocks[count[k]] b2 = blocks[p] name, l = merge(b1, b2, list(blocks.keys()), from_start = False) if l == 1: continue if l == min(len(b1),len(b2)): if len(b1) == len(b2): replace_target(preds[count[k]] + preds[p], blocks, [count[k], p], name) del blocks[count[k]] del blocks[p] return True if len(b1) < len(b2): small_block = count[k] large_block = p else: small_block = p large_block = count[k] blocks[large_block] = blocks[large_block][:len(blocks[large_block]) - l] jmp = {'op': 'jmp', "args": [small_block]} blocks[large_block].append(jmp) else: jmp = {'op': 'jmp', "args": [name]} new_block = b1[len(b1) - l:] blocks[name] = new_block blocks[count[k]] = b1[:len(b1) - l] blocks[count[k]].append(jmp) blocks[p] = b2[:len(b2) - l] blocks[p].append(jmp) return True # merge two succs if blocks[block][-1] is not None and blocks[block][-1]['op'] == 'br': args = blocks[block][-1]['args'] b1 = blocks[args[1]] b2 = blocks[args[2]] name, l = merge(b1, b2, list(blocks.keys()),from_start = True) if l > 0: if l == len(b1): # cannot have jmp in middle of block # so this is the only case such that a block is entirely duplicated jmp = {'op': 'jmp', "args": [args[1]]} blocks[block] = blocks[block][:-1] blocks[block].append(jmp) replace_target(preds[args[2]], blocks, [args[2]], args[1]) del blocks[args[2]] else: jmp = {'op': 'jmp', "args": [name]} br = blocks[block][-1] blocks[block] = blocks[block][:-1] blocks[block].append(jmp) replace_target(preds[args[1]] + preds[args[2]], blocks, args[1:3], name) blocks[name] = b1[:l] blocks[args[1]] = b1[l:] blocks[args[2]] = b2[l:] blocks[name].append(br) return True return False