class SyntaxTree::YARV::SeaOfNodes
flow.
to the graph. The edges of the graph represent either control flow or data
instruction in the instruction sequence or a synthesized node that we add
allows us to have the vertices of the graph represent either an
represent both control and data flow in the same graph. The way we use it
A sea of nodes is an intermediate representation used by a compiler to
def self.compile(dfg)
def self.compile(dfg) Compiler.new(dfg).compile end
def initialize(dfg, nodes, local_graphs)
def initialize(dfg, nodes, local_graphs) @dfg = dfg @nodes = nodes @local_graphs = local_graphs end
def to_mermaid
def to_mermaid Mermaid.flowchart do |flowchart| nodes.each do |node| flowchart.node("node_#{node.id}", node.label, shape: :rounded) end nodes.each do |producer| producer.outputs.each do |consumer_edge| label = if !consumer_edge.label # No label. elsif consumer_edge.to.is_a?(PhiNode) # Edges into phi nodes are labelled by the offset of the # instruction going into the merge. "%04d" % consumer_edge.label else consumer_edge.label.to_s end flowchart.link( flowchart.fetch("node_#{producer.id}"), flowchart.fetch("node_#{consumer_edge.to.id}"), label, type: consumer_edge.type == :info ? :dotted : :directed, color: { data: :green, control: :red }[consumer_edge.type] ) end end end end
def verify
def verify # Verify edge labels. nodes.each do |node| # Not talking about phi nodes right now. next if node.is_a?(PhiNode) if node.is_a?(InsnNode) && node.insn.branch_targets.any? && !node.insn.is_a?(Leave) # A branching node must have at least one branch edge and # potentially a fallthrough edge coming out. labels = node.outputs.map(&:label).sort raise if labels[0] != :branch0 raise if labels[1] != :fallthrough && labels.size > 2 else labels = node.inputs.filter { |e| e.type == :data }.map(&:label) next if labels.empty? # No nil labels raise if labels.any?(&:nil?) # Labels should start at zero. raise unless labels.min.zero? # Labels should be contiguous. raise unless labels.sort == (labels.min..labels.max).to_a end end end