# 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
# 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)
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))
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
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`
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
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)
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
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
# 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)
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)
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
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
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
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
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)
# 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)
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