Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add AST normalizer.

  • Loading branch information...
commit d95f9f2d7ea8ca7c470093ba45287c3808a9cf16 1 parent 5fa16a8
@whitequark authored
View
12 bin/furnace-avm2
@@ -27,7 +27,7 @@ require "benchmark"
include Furnace
-GRAPH_FORMATS = %w(none graphviz)
+GRAPH_FORMATS = %w(none text graphviz)
opts = Trollop::options do
version "furnace-avm2 #{AVM2::VERSION}"
@@ -44,9 +44,9 @@ EOS
opt :threads, "Use <i> threads for processing", :default => 1
- opt :only, "Only operate on methods <i+>", :type => :ints, :short => '-O'
- opt :except, "Operate on all methods except <i+>", :type => :ints, :short => '-E'
- opt :grep, "Search <s> in method names", :type => :string, :short => '-g'
+ opt :only, "Only operate on methods <i+>", :type => :ints, :short => '-O'
+ opt :except, "Operate on all methods except <i+>", :type => :ints, :short => '-E'
+ opt :grep, "Search <s> in method names", :type => :string, :short => '-g'
opt :collect, "Collect failed methods instead of exiting", :default => false
opt :sort_by_size, "Sort methods by body size", :default => false
@@ -54,8 +54,8 @@ EOS
opt :fix_names, "Remove invalid characters from names", :default => true, :short => '-q'
opt :cfg, "Emit CFG in specified format for methods", :type => :string, :short => '-G'
- opt :nf, "Build NF-AST", :default => false
- opt :decompile, "Decompile methods", :default => false
+ opt :nf, "Build NF-AST", :default => false, :short => '-n'
+ opt :decompile, "Decompile methods", :default => false, :short => '-d'
end
Trollop::die "Stray arguments: #{ARGV}" unless ARGV.empty?
View
4 lib/furnace-avm2/transform/cfg_build.rb
@@ -41,7 +41,9 @@ def transform(code, body)
end
end
- unless [ABC::AS3Jump, ABC::AS3Label].include? opcode.class
+ # Skip nops
+ unless [ ABC::AS3Jump, ABC::AS3Label,
+ ABC::AS3Kill, ABC::AS3Nop ].include? opcode.class
@pending_queue << opcode
end
View
4 lib/furnace-avm2/transform/nf_normalize.rb
@@ -12,6 +12,10 @@ def transform(nf)
@nf
end
+ def on__info(node)
+ node.update(:remove)
+ end
+
def remove_useless_return
if @nf.children.last.type == :return_void
@nf.children.slice! -1
View
13 lib/furnace-avm2/transform/ssa_dicm.rb
@@ -12,27 +12,27 @@ def transform(cfg, info)
changed = false
- puts " =============== #{block.label}"
+ #puts " =============== #{block.label}"
block_info = info[block]
block_info[:sets].each do |id|
- src_node = block_info[:set_map][id]
+ src_node = block_info[:set_map][id]
targets = ([ block ] + block.targets).select do |target|
info[target][:gets].include? id
end
- if targets.one?
+ if !src_node.nil? && targets.one?
target = targets.first
target_info = info[target]
- p target_info[:gets_map]
+ #p target_info[:gets_map]
if target_info[:gets_map][id].one?
dst_node = target_info[:gets_map][id].first
dst_upper = target_info[:gets_upper][dst_node]
- p src_node, dst_node, dst_upper
+ #p src_node, dst_node, dst_upper
do_move = false
@@ -64,8 +64,7 @@ def transform(cfg, info)
end
end
elsif targets.empty?
- if src_node.metadata[:read_barrier].empty? &&
- src_node.metadata[:write_barrier].empty?
+ if src_node.nil? || src_node.metadata[:write_barrier].empty?
block.insns.delete src_node
block_info[:sets].delete id
View
43 lib/furnace-avm2/transform/ssa_transform.rb
@@ -1,12 +1,51 @@
module Furnace::AVM2
module Transform
class SSATransform
+ class ASTNormalizer
+ include Furnace::AST::StrictVisitor
+
+ # (if-* a b) -> (branch-if (*' a b))
+ BINARY_IF_MAPPING = {
+ :eq => [false, :==],
+ :ne => [false, :!=],
+ :ge => [false, :>=],
+ :nge => [true, :>=],
+ :gt => [false, :>],
+ :ngt => [true, :>],
+ :le => [false, :<=],
+ :nle => [true, :<=],
+ :lt => [false, :<],
+ :nlt => [true, :<],
+ :strict_eq => [false, :===],
+ :strict_ne => [true, :===], # Why? Because of (lookup-switch ...).
+ }
+
+ BINARY_IF_MAPPING.each do |cond, (positive, comp)|
+ define_method :"on_if_#{cond}" do |node|
+ node.update(:branch_if, [
+ positive,
+ AST::Node.new(comp, node.children)
+ ])
+ end
+ end
+
+ [true, false].each do |cond|
+ define_method :"on_if_#{cond}" do |node|
+ node.update(:branch_if, [
+ cond,
+ node.children.first
+ ])
+ end
+ end
+ end
+
def transform(cfg)
@cfg = cfg
@stacks = { cfg.entry => [] }
-
info = {}
+ normalizer = ASTNormalizer.new
+
next_rid = 0
worklist = Set[cfg.entry]
visited = Set[]
@@ -62,6 +101,8 @@ def transform(cfg)
node.children.concat opcode.parameters
node.children.concat parameters
+ normalizer.visit node
+
nodes.push(toplevel_node)
if block.cti == opcode
Please sign in to comment.
Something went wrong with that request. Please try again.