X-Git-Url: http://nitlanguage.org diff --git a/src/ssa.nit b/src/ssa.nit index b0e1bbe..dbaac2e 100644 --- a/src/ssa.nit +++ b/src/ssa.nit @@ -102,6 +102,9 @@ class BasicBlock # Used to handle recursions by treating only one time each block var treated: Bool = false + # Used to dump the BasicBlock to dot + var treated_debug: Bool = false + # If true, the iterated dominance frontier of this block has been computed var df_computed: Bool = false @@ -205,6 +208,15 @@ redef class APropdef # Generate all basic blocks for this code fun generate_basic_blocks(ssa: SSA) is abstract + # Contain all AST-parts related to object mechanisms the propdef has: + # instantiation, method dispatch, attribute access, subtyping-test + var object_sites: Array[AExpr] = new Array[AExpr] + + # The return variable of the propdef + # Create an empty variable for the return of the method + # and treat returns like variable assignments + var returnvar: Variable = new Variable("returnvar") + # Compute the three steps of SSA-algorithm # `ssa` A new instance of SSA class initialized with `self` fun compute_ssa(ssa: SSA) @@ -463,6 +475,9 @@ redef class AAttrPropdef basic_block.first = self basic_block.last = self + # Add the return variable + variables.add(returnvar) + # Add the self variable if self.selfvariable != null then variables.add(selfvariable.as(not null)) @@ -475,12 +490,6 @@ redef class AAttrPropdef end redef class AMethPropdef - - # The return variable of the propdef - # Create an empty variable for the return of the method - # and treat returns like variable assignments - var returnvar: Variable = new Variable("returnvar") - redef fun generate_basic_blocks(ssa: SSA) do basic_block = new BasicBlock @@ -510,6 +519,57 @@ redef class AMethPropdef end end +# Utility class for dump basic block and SSA output to dot files +class BlockDebug + # The output file + var file: FileWriter + + # Dump all the hierarchy of BasicBlock from `block` to the leaves + fun dump(block: BasicBlock) + do + # Write the basic blocks hierarchy in output file + file.write("digraph basic_blocks\n\{\n") + var i = 0 + file.write(print_block(block, i)) + file.write("\n\}") + + file.close + end + + # Print all the block recursively from `block` to the leaves + # *`block` The root BasicBlock + # *`i` Used for the recursion + private fun print_block(block: BasicBlock, i: Int): String + do + # Precise the type and location of the begin and end of current block + var s = "block{block.hash.to_s} [shape=record, label="+"\"\{" + s += "block" + block.to_s.escape_to_dot + s += "|\{" + block.first.location.file.filename.to_s + block.first.location.line_start.to_s + s += " | " + block.first.to_s.escape_to_dot + + # Print phi-functions if any + for phi in block.phi_functions do + s += " | " + phi.to_s.escape_to_dot + " " + end + + s += "}|\{" + block.last.location.file.filename.to_s + block.last.location.line_start.to_s + s += " | " + block.last.to_s.escape_to_dot + "}}\"];"+ "\n" + + i += 1 + block.treated_debug = true + + for b in block.successors do + # Print edges to successors + s += "block{block.hash.to_s} -> " + " block{b.hash.to_s};\n" + + # Recursively print child blocks + if not b.treated_debug then s += print_block(b, i) + end + + return s + end +end + redef class AExpr # Generate recursively basic block for this expression # *`ssa` An instance of the SSA class initialized with the enclosing `APropdef` @@ -620,9 +680,7 @@ redef class AReturnExpr old_block = self.n_expr.generate_basic_blocks(ssa, old_block) # Store the return expression in the dependences of the dedicated returnvar - if ssa.propdef isa AMethPropdef then - ssa.propdef.as(AMethPropdef).returnvar.dep_exprs.add(n_expr.as(not null)) - end + ssa.propdef.returnvar.dep_exprs.add(n_expr.as(not null)) end old_block.last = self @@ -648,7 +706,7 @@ redef class AAssertExpr self.n_else.generate_basic_blocks(ssa, block_false) else block_false.first = self - block_false.first = self + block_false.last = self end old_block.link(block_false) @@ -742,6 +800,8 @@ end redef class AIsaExpr redef fun generate_basic_blocks(ssa, old_block) do + ssa.propdef.object_sites.add(self) + return self.n_expr.generate_basic_blocks(ssa, old_block) end end @@ -749,6 +809,8 @@ end redef class AAsCastExpr redef fun generate_basic_blocks(ssa, old_block) do + ssa.propdef.object_sites.add(self) + return self.n_expr.generate_basic_blocks(ssa, old_block) end end @@ -780,6 +842,8 @@ redef class ASendExpr # A call does not finish the current block, # because we create intra-procedural basic blocks here + ssa.propdef.object_sites.add(self) + # Recursively goes into arguments to find variables if any for e in self.raw_arguments do e.generate_basic_blocks(ssa, old_block) @@ -792,6 +856,8 @@ redef class ASendReassignFormExpr do self.n_expr.generate_basic_blocks(ssa, old_block) + ssa.propdef.object_sites.add(self) + # Recursively goes into arguments to find variables if any for e in self.raw_arguments do e.generate_basic_blocks(ssa, old_block) @@ -814,6 +880,8 @@ redef class ANewExpr do for e in self.n_args.n_exprs do e.generate_basic_blocks(ssa, old_block) + ssa.propdef.object_sites.add(self) + return old_block end end @@ -821,6 +889,8 @@ end redef class AAttrExpr redef fun generate_basic_blocks(ssa, old_block) do + ssa.propdef.object_sites.add(self) + return self.n_expr.generate_basic_blocks(ssa, old_block) end end @@ -828,6 +898,8 @@ end redef class AAttrAssignExpr redef fun generate_basic_blocks(ssa, old_block) do + ssa.propdef.object_sites.add(self) + return self.n_expr.generate_basic_blocks(ssa, old_block) end end @@ -835,6 +907,8 @@ end redef class AAttrReassignExpr redef fun generate_basic_blocks(ssa, old_block) do + ssa.propdef.object_sites.add(self) + return self.n_expr.generate_basic_blocks(ssa, old_block) end end @@ -1002,13 +1076,15 @@ redef class AWhileExpr old_block.link(block) self.n_expr.generate_basic_blocks(ssa, old_block) - var inside_block = self.n_block.generate_basic_blocks(ssa, block) + self.n_block.generate_basic_blocks(ssa, block) # Link the inside of the block to the previous block block.link_special(old_block) # Create a new Block after the while var new_block = new BasicBlock + new_block.first = self + new_block.last = self new_block.need_update = true old_block.link_special(new_block) @@ -1041,15 +1117,17 @@ redef class AForExpr # The beginning of the block is the first instruction var block = new BasicBlock - block.first = self.n_expr + block.first = self.n_groups.first.n_expr block.last = self.n_block.as(not null) - # Visit the test of the if - self.n_expr.generate_basic_blocks(ssa, block) + for g in n_groups do + # Visit the test of the if + g.n_expr.generate_basic_blocks(ssa, block) - # Collect the variables declared in the for - for v in variables do - ssa.propdef.variables.add(v) + # Collect the variables declared in the for + for v in g.variables do + ssa.propdef.variables.add(v) + end end old_block.link(block) @@ -1057,6 +1135,9 @@ redef class AForExpr block.link(old_block) var new_block = new BasicBlock + new_block.first = self + new_block.last = self + new_block.need_update = true return new_block