lib/html: implement the tag list as an hashset instead of a array.
[nit.git] / src / ssa.nit
index b0e1bbe..dbaac2e 100644 (file)
@@ -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