# 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]
+
# Compute the three steps of SSA-algorithm
# `ssa` A new instance of SSA class initialized with `self`
fun compute_ssa(ssa: SSA)
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`
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