def run_on_module(self, node): draw_header("x86 Code Generation") # Generate code for "main" if "main" not in node.functions: raise Exception("No main function in the IR") self.visit(node.functions["main"], [])
def run_on_function(self, node): draw_header("Instruction Combining: %s" % node.name) func = node for bb in func.basic_blocks: self.visit_basicblock(bb) print(node)
def run_on_module(self, node): draw_header("Javascript Code Generation") # Generate code for "main" if "main" not in node.functions: raise Exception("No main function in the IR") self.visit(node.functions["main"], [])
def run_on_function(self, node): draw_header("Constant Propagation: %s" % node.name) func = node for bb in func.basic_blocks: self.visit_basicblock(bb) print(node)
def main(): filename = sys.argv[1] fptr = open(filename, "r") source = fptr.read() draw_header("Python Source") print(source) tree = create_ast(source, filename) generate_ir(tree)
def generate_ir(tree): ir_generator = IRGenerator() ir_generator.visit(tree) module = ir_generator.module draw_header("IR") print(module) # codegen = x86CodeGen() codegen = JSCodeGen() structurizer = StructurizerAnalysisPass() dom_tree_pass = DominatorTreeConstructorPass() passmgr = PassManager() passmgr.add_function_pass(dom_tree_pass) passmgr.add_function_pass(ConstPropagationPass()) passmgr.add_function_pass(RenderCFGPass()) passmgr.add_function_pass(structurizer) passmgr.add_module_pass(codegen) passmgr.run(module) # block = x86.Block() # block.append(x86.imul(x86.eax, x86.ebx)) # # inst = x86.mov(x86.eax, 50) # b = inst.bytes() # # bytes = block.assemble() # inst = x86.imul(x86.eax, x86.ebx) # b = inst.bytes() # bytes = codegen.get_assembly_bytes() # print(bytes) # x86bytes = create_bytes(bytes) # x86bytes = x86.mov(x86.eax, 50).bytes() # x86bytes += x86.ret().bytes() # # x86bytes = bytes(x86bytes) # x86 Code Generation # res = jitter.jit(x86bytes) # print("Function Return Result: %s" % res) # Javascript Code Generation js = codegen.get_code() print(js)
def run_on_function(self, node): entry_block = node.basic_blocks[0] Q = Queue() Q.put(entry_block) indent = " " * 4 dot_str = "digraph g {\n" dot_str += indent + "node [shape=box];\n" visited = [] while not Q.empty(): bb = Q.get() if bb in visited: continue visited.append(bb) terminator = bb.get_terminator() true_block = None false_block = None if isinstance(terminator, ConditionalBranchInstruction): true_block = terminator.bb_true false_block = terminator.bb_false # Now from bb add all the successor blocks for succ in bb.successors: label = ";\n" if succ == true_block: label = "[label=True]" + label elif succ == false_block: label = "[label=False]" + label dot_str += indent + bb.name + " -> " + succ.name dot_str += label Q.put(succ) dot_str += "}" draw_header("Control Flow Graph: %s" % node.name) print("Visualize this graph at: http://mdaines.github.io/viz.js/") print(dot_str)
def run_on_function(self, func): draw_header("Post Dominator Tree Constructor") post_dom_tree = DominanceTree() start_node = func.exit_block post_dom_tree.add_dom_blk(start_node, start_node) for bb in func.basic_blocks: if bb != start_node: post_dom_tree.add_dom(bb, [bb for bb in func.basic_blocks]) changed = True while changed: changed = False post_order_blks = post_order_traversal(func) for blk in post_order_blks: # For each n in N - {n0} if blk != start_node: new_idom = set(post_dom_tree.get_dom(blk)) for pred in blk.successors: doms = post_dom_tree.get_dom(pred) doms = set(doms) new_idom = new_idom.intersection(doms) new_idom.add(blk) prev_dom = post_dom_tree.get_dom(blk) new_idom = list(new_idom) if new_idom != prev_dom: post_dom_tree.add_dom(blk, new_idom) changed = True self.post_dom_tree = post_dom_tree print(post_dom_tree)
def run_on_function(self, node): draw_header("Structurizer: %s" % node.name) func = node self.create_nested_and_cfb_blocks(func) # Create a new queue for BFS queue = Queue() self.root_node = self.get_merged_bb(func.entry_block) queue.put(self.root_node) visited = [] while not queue.empty(): merged_bb = queue.get() bb = merged_bb.bb process = True if bb in visited and not merged_bb.processed: # Then we have found a terminating condition. # Find the root off this control flow block converge_point = merged_bb cfb = self.find_nearest_cfb_parent_block(merged_bb) cfb.next = converge_point process = False cfb.processed = True visited.append(bb) if process: terminator = bb.get_terminator() if isinstance(terminator, ConditionalBranchInstruction): # Start a visited stack # Start with an If-else block cfb = self.get_cfb(bb) cfb.true_block = self.get_merged_bb(terminator.bb_true) cfb.true_block.parent = cfb cfb.false_block = self.get_merged_bb(terminator.bb_false) cfb.false_block.parent = cfb cfb.parent = merged_bb self.control_flow_stack.append(cfb) queue.put(cfb.true_block) queue.put(cfb.false_block) elif isinstance(terminator, BranchInstruction): # Find the branch where it terminates to branch_to_bb = terminator.basic_block branch_to_bb_merged = self.get_merged_bb(branch_to_bb) branch_to_bb_merged.parent = merged_bb queue.put(merged_bb.next) else: assert isinstance(terminator, ReturnInstruction) node = self.root_node # Merge all the branches which have a branch instruction. Stop only when we see Conditional branch self.merge(node) print("-" * 100)