Permalink
Browse files

Huge SSA improvements.

  • Loading branch information...
1 parent 7f15f7d commit ece426a2564e34581ccb15b8f555b3a0dc41ef8b @whitequark committed Jan 2, 2013
View
@@ -5,3 +5,4 @@ pkg/*
*.sublime-*
doc/
.yardoc/
+coverage/
View
@@ -17,8 +17,12 @@ Gem::Specification.new do |s|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
+ s.add_dependency 'ansi'
+
s.add_development_dependency 'rake'
s.add_development_dependency 'bacon', '~> 1.2'
+ s.add_development_dependency 'bacon-colored_output'
+ s.add_development_dependency 'simplecov'
s.add_development_dependency 'yard'
s.add_development_dependency 'redcarpet'
end
View
@@ -9,14 +9,27 @@ def self.inspect_type(type)
end
end
+ require_relative 'ssa/pretty_printer'
+
+ require_relative 'ssa/void'
+
require_relative 'ssa/value'
- require_relative 'ssa/immediate'
+ require_relative 'ssa/constant'
+ require_relative 'ssa/named_value'
+ require_relative 'ssa/argument'
+ require_relative 'ssa/user'
+
require_relative 'ssa/instruction'
- require_relative 'ssa/instructions/jump'
- require_relative 'ssa/instructions/assign'
+ require_relative 'ssa/generic_instruction'
+
require_relative 'ssa/instructions/phi'
+ require_relative 'ssa/instructions/branch'
require_relative 'ssa/instructions/return'
+
require_relative 'ssa/basic_block'
require_relative 'ssa/function'
+
+ require_relative 'ssa/module'
+
require_relative 'ssa/builder'
end
@@ -0,0 +1,10 @@
+module Furnace
+ class SSA::Argument < SSA::NamedValue
+ attr_accessor :type
+
+ def initialize(function, type, name)
+ super(function, name)
+ @type = type
+ end
+ end
+end
@@ -1,26 +1,56 @@
-module Furnace::SSA
- class BasicBlock
- attr_reader :function, :label
+module Furnace
+ class SSA::BasicBlock < SSA::NamedValue
+ def initialize(function, name=nil, insns=[])
+ super(function, name)
+ @instructions = insns
+ end
- attr_accessor :instructions
+ def to_a
+ @instructions.dup
+ end
- alias :insns :instructions
- alias :insns= :instructions=
+ def include?(instruction)
+ @instructions.include? instruction
+ end
+
+ def each(&proc)
+ @instructions.each(&proc)
+ end
- def initialize(function, insns=[], label=function.make_label)
- @function, @label, @instructions = function, label, insns
+ def append(instruction)
+ @instructions.push instruction
+ end
+
+ alias << append
+
+ def insert(before, instruction)
+ unless index = @instructions.index(before)
+ raise ArgumentError, "Instruction #{before} is not found"
+ end
+
+ @instructions.insert index, instruction
+ end
+
+ def replace(instruction, replace_with)
+ insert instruction, replace_with
+ remove instruction
+ end
+
+ def remove(instruction)
+ @instructions.delete instruction
end
def control_transfer_instruction
@instructions.last
end
+ alias control_transfer_insn control_transfer_instruction
- def successor_labels
+ def successor_names
control_transfer_instruction.uses.
select do |value|
- value.type == BasicBlock
+ value.type == SSA::BasicBlock
end.map do |value|
- value.value
+ value.name
end
end
@@ -30,34 +60,38 @@ def successors
end
end
- def predecessor_labels
- predecessors.map(&:label)
+ def predecessor_names
+ predecessors.map(&:name)
end
def predecessors
- @function.predecessors_for(self)
+ @function.predecessors_for(@label)
end
def returns?
successor_labels.empty?
end
- def to_value
- Immediate.new(@label, BasicBlock)
+ def constant?
+ true
end
- def self.inspect_as_type
- 'label'
- end
+ def pretty_print(p=SSA::PrettyPrinter.new)
+ p.text @name, ":"
+ p.newline
- def inspect
- string = "#{@label}:\n"
+ each do |insn|
+ p << ' '
+ insn.pretty_print(p)
+ p.newline
+ end
- string << @instructions.map do |insn|
- " #{insn.inspect}"
- end.join("\n")
+ p
+ end
- string
+ def inspect_as_value(p=SSA::PrettyPrinter.new)
+ p.keyword 'label'
+ p.name name
end
end
end
View
@@ -1,51 +1,57 @@
-module Furnace::SSA
- class Builder
+module Furnace
+ class SSA::Builder
attr_reader :function
- attr_accessor :current_block
+ attr_accessor :block
- def initialize(arguments=[], return_type=nil)
- @function = Function.new(arguments, return_type)
-
- entry = block
- @function.entry = entry
+ def initialize(name, arguments=[], return_type=nil)
+ @function = SSA::Function.new(name, [], return_type)
+ @function.arguments = arguments.map do |(type, name)|
+ SSA::Argument.new(@function, type, name)
+ end
- @current_block = entry
+ @block = @function.entry = add_block
end
- def block
- block = BasicBlock.new(@function)
+ def add_block
+ block = SSA::BasicBlock.new(@function)
@function.add block
block
end
- def goto(block)
- @current_block = block
+ def with(block)
+ old_block = @block
+ @block = block
+
+ yield old_block
+ ensure
+ @block = old_block
end
def insn(instruction, *uses)
- insn = instruction.new(@current_block, uses)
- @current_block.instructions << insn
+ insn = instruction.new(@block, uses)
+ @block.append insn
- insn.defs
+ insn
end
- def assign(value)
- result, = insn(Assign, value)
- result
+ def typed_insn(instruction, type, *uses)
+ insn = instruction.new(@block, type, uses)
+ @block.append insn
+
+ insn
end
- def jump(block)
- insn(Jump, Immediate.new(BasicBlock, block.label))
+ def branch(block)
+ insn(SSA::Branch, block.to_value)
end
- def phi(*uses)
- result, = insn(Phi, *uses)
- result
+ def phi(type, *uses)
+ typed_insn(SSA::Phi, type, *uses)
end
def return(value)
- insn(Return, value)
+ insn(SSA::Return, value)
nil
end
@@ -55,13 +61,11 @@ def cond(instruction, *uses)
end
def switch(instruction, *uses, successor_count)
- successors = successor_count.times.map { block }
+ successors = successor_count.times.map { add_block }
- labels = successors.map do |succ|
- Immediate.new(BasicBlock, succ.label)
- end
+ insn(instruction, *uses, *successors.map(&:to_value))
- insn(instruction, *uses, *labels)
+ @block = add_block
successors
end
@@ -0,0 +1,31 @@
+module Furnace
+ class SSA::Constant < SSA::Value
+ attr_reader :type
+ attr_reader :value
+
+ def initialize(type, value)
+ @value, @type = value, type
+ end
+
+ def constant?
+ true
+ end
+
+ def ==(other)
+ if other.respond_to? :to_value
+ other_value = other.to_value
+
+ other_value.constant? &&
+ other_value.type == type &&
+ other_value.value == value
+ else
+ false
+ end
+ end
+
+ def inspect_as_value(p=SSA::PrettyPrinter.new)
+ p.type type
+ p.text @value.inspect
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit ece426a

Please sign in to comment.