seafoam 0.8 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bgv2isabelle +1 -5
  3. data/bin/bgv2json +1 -5
  4. data/bin/cfg2asm +1 -5
  5. data/bin/seafoam +1 -5
  6. data/lib/seafoam/commands.rb +48 -31
  7. data/lib/seafoam/graal/pi.rb +18 -0
  8. data/lib/seafoam/graph.rb +9 -1
  9. data/lib/seafoam/graphviz_writer.rb +3 -0
  10. data/lib/seafoam/json_writer.rb +1 -3
  11. data/lib/seafoam/{annotators → passes}/fallback.rb +4 -4
  12. data/lib/seafoam/{annotators → passes}/graal.rb +43 -13
  13. data/lib/seafoam/passes/truffle.rb +58 -0
  14. data/lib/seafoam/passes.rb +61 -0
  15. data/lib/seafoam/version.rb +1 -1
  16. data/lib/seafoam.rb +5 -4
  17. metadata +23 -60
  18. data/.github/probots.yml +0 -2
  19. data/.github/workflows/workflows.yml +0 -40
  20. data/.gitignore +0 -6
  21. data/.rubocop.yml +0 -37
  22. data/.ruby-version +0 -1
  23. data/.seafoam/config +0 -1
  24. data/CODE_OF_CONDUCT.md +0 -128
  25. data/CONTRIBUTING.md +0 -5
  26. data/Gemfile +0 -2
  27. data/Gemfile.lock +0 -59
  28. data/LICENSE.md +0 -7
  29. data/README.md +0 -378
  30. data/demos/box-unbox-stats +0 -65
  31. data/docs/annotators.md +0 -43
  32. data/docs/bgv.md +0 -294
  33. data/docs/getting-graphs.md +0 -63
  34. data/docs/images/igv.png +0 -0
  35. data/docs/images/seafoam.png +0 -0
  36. data/docs/images/spotlight-igv.png +0 -0
  37. data/docs/images/spotlight-seafoam.png +0 -0
  38. data/docs/json.md +0 -35
  39. data/examples/Fib.java +0 -24
  40. data/examples/MatMult.java +0 -39
  41. data/examples/fib-java.bgv.gz +0 -0
  42. data/examples/fib.js +0 -15
  43. data/examples/fib.rb +0 -15
  44. data/examples/identity.rb +0 -13
  45. data/examples/java/Irreducible.class +0 -0
  46. data/examples/java/Irreducible.j +0 -35
  47. data/examples/java/IrreducibleDecompiled.java +0 -21
  48. data/examples/java/JavaExamples.java +0 -418
  49. data/examples/matmult.rb +0 -29
  50. data/examples/overflow.rb +0 -13
  51. data/examples/ruby/clamps.rb +0 -20
  52. data/examples/ruby/graal.patch +0 -15
  53. data/examples/ruby/ruby_examples.rb +0 -278
  54. data/lib/seafoam/annotators.rb +0 -54
  55. data/lib/seafoam/config.rb +0 -34
  56. data/seafoam.gemspec +0 -22
  57. data/spec/seafoam/annotators/fallback_spec.rb +0 -69
  58. data/spec/seafoam/annotators/graal_spec.rb +0 -96
  59. data/spec/seafoam/annotators_spec.rb +0 -61
  60. data/spec/seafoam/bgv/bgv_parser_spec.rb +0 -167
  61. data/spec/seafoam/binary/io_binary_reader_spec.rb +0 -176
  62. data/spec/seafoam/cfg/cfg_parser_spec.rb +0 -21
  63. data/spec/seafoam/cfg/disassembler_spec.rb +0 -32
  64. data/spec/seafoam/command_spec.rb +0 -314
  65. data/spec/seafoam/graph_spec.rb +0 -172
  66. data/spec/seafoam/graphviz_writer_spec.rb +0 -63
  67. data/spec/seafoam/json_writer_spec.rb +0 -14
  68. data/spec/seafoam/spec_helpers.rb +0 -34
  69. data/spec/seafoam/spotlight_spec.rb +0 -38
  70. data/tools/render-all +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f5cdd6b29d9c25bc7db525b2f49d6937fb996bc108a7bf18ddf0364575e6999
4
- data.tar.gz: 510608b5d784ef4c58768aafb42372bdd33aad226a6123e9ad72ea77845a8050
3
+ metadata.gz: 49d090779b04322f8c82aae0cf11ea2e39cd4cef1f3d9dc2b51de1f27e565f9c
4
+ data.tar.gz: 121f1c7bb327c30f1a388960012c43dab49e0f1079d5a420811ab2332de9663b
5
5
  SHA512:
6
- metadata.gz: 125d9c14699c1a9a72bc1311b2673cf24d725af3c4da38eac1c2c89ebce4d6157c3e08ad7cc7b8769f8c755227cd04da4b9a6f53ae30f0f3ce38e7a1cf12d4b2
7
- data.tar.gz: 2430c0b5f04378767c5bbbb51274900deae22291fd905831f4a5d5847edd5e7497e3df94a434ab803689ee4f9b3f6cd5d6740bdc28dbf96d7da329c8610ac6e5
6
+ metadata.gz: dd13ee2efe4fe4118fc5f6bdb56c55b3c1c5f28b86a3d37ce3cf4fc72bcdcbeb161968260b62626047b9f9f9eedec53cbc743d79512a11bd77b195f054c54262
7
+ data.tar.gz: 67e06a4e89fdf9e6297e3d68da7f7b0e7d4f1de95a97c9be17c12e6c9114476ee6e747c6306c3bc472e549317f20c19c315c9789d1814c68fdd85501327c432b
data/bin/bgv2isabelle CHANGED
@@ -5,12 +5,8 @@ require 'seafoam'
5
5
  # This is the 'bgv2isabelle' command line entry point.
6
6
 
7
7
  begin
8
- # Load configuraiton.
9
- config = Seafoam::Config.new
10
- config.load_config
11
-
12
8
  # Run the command line.
13
- commands = Seafoam::Commands.new($stdout, config)
9
+ commands = Seafoam::Commands.new($stdout)
14
10
  commands.bgv2isabelle(*ARGV)
15
11
  rescue StandardError => e
16
12
  if $DEBUG
data/bin/bgv2json CHANGED
@@ -5,12 +5,8 @@ require 'seafoam'
5
5
  # This is the 'bgv2json' command line entry point.
6
6
 
7
7
  begin
8
- # Load configuraiton.
9
- config = Seafoam::Config.new
10
- config.load_config
11
-
12
8
  # Run the command line.
13
- commands = Seafoam::Commands.new($stdout, config)
9
+ commands = Seafoam::Commands.new($stdout)
14
10
  commands.bgv2json(*ARGV)
15
11
  rescue StandardError => e
16
12
  if $DEBUG
data/bin/cfg2asm CHANGED
@@ -5,12 +5,8 @@ require 'seafoam'
5
5
  # This is the 'cfg2asm' command line entry point.
6
6
 
7
7
  begin
8
- # Load configuraiton.
9
- config = Seafoam::Config.new
10
- config.load_config
11
-
12
8
  # Run the command line.
13
- commands = Seafoam::Commands.new($stdout, config)
9
+ commands = Seafoam::Commands.new($stdout)
14
10
  commands.cfg2asm(*ARGV)
15
11
  rescue StandardError => e
16
12
  if $DEBUG
data/bin/seafoam CHANGED
@@ -5,12 +5,8 @@ require 'seafoam'
5
5
  # This is the 'seafoam' command line entry point.
6
6
 
7
7
  begin
8
- # Load configuraiton.
9
- config = Seafoam::Config.new
10
- config.load_config
11
-
12
8
  # Run the command line.
13
- commands = Seafoam::Commands.new($stdout, config)
9
+ commands = Seafoam::Commands.new($stdout)
14
10
  commands.seafoam(*ARGV)
15
11
  rescue StandardError => e
16
12
  if $DEBUG
@@ -3,9 +3,8 @@ require 'json'
3
3
  module Seafoam
4
4
  # Implementations of the command-line commands that you can run in Seafoam.
5
5
  class Commands
6
- def initialize(out, config)
6
+ def initialize(out)
7
7
  @out = out
8
- @config = config
9
8
  end
10
9
 
11
10
  # Run the general seafoam command.
@@ -15,25 +14,7 @@ module Seafoam
15
14
  when nil, 'help', '-h', '--help', '-help'
16
15
  raise ArgumentError, "unexpected arguments #{args.join(' ')}" unless args.empty?
17
16
 
18
- @out.puts 'seafoam file.bgv info'
19
- @out.puts ' file.bgv list'
20
- @out.puts ' file.bgv[:graph][:node[-edge]] search term...'
21
- @out.puts ' file.bgv[:graph][:node[-edge]] edges'
22
- @out.puts ' file.bgv[:graph][:node[-edge]] props'
23
- @out.puts ' file.bgv:graph:node source'
24
- @out.puts ' file.bgv:graph render'
25
- @out.puts ' --spotlight n,n,n...'
26
- @out.puts ' --out graph.pdf'
27
- @out.puts ' graph.svg'
28
- @out.puts ' graph.png'
29
- @out.puts ' graph.dot'
30
- @out.puts ' --show-frame-state'
31
- @out.puts ' --hide-floating'
32
- @out.puts ' --no-reduce-edges'
33
- @out.puts ' --draw-blocks'
34
- @out.puts ' --option key value'
35
- @out.puts ' --help'
36
- @out.puts ' --version'
17
+ help(*args)
37
18
  when 'version', '-v', '-version', '--version'
38
19
  version(*args)
39
20
  else
@@ -263,7 +244,7 @@ module Seafoam
263
244
  end
264
245
 
265
246
  def search_object(tag, object, terms)
266
- full_text = JSON.generate(object)
247
+ full_text = JSON.generate(JSONWriter.prepare_json(object))
267
248
  full_text_down = full_text.downcase
268
249
  start = 0
269
250
  terms.each do |t|
@@ -299,7 +280,7 @@ module Seafoam
299
280
  parser.read_graph_header
300
281
  graph = parser.read_graph
301
282
  if node_id
302
- Annotators.apply graph
283
+ Passes.apply graph
303
284
  node = graph.nodes[node_id]
304
285
  raise ArgumentError, 'node not found' unless node
305
286
 
@@ -398,8 +379,10 @@ module Seafoam
398
379
  raise ArgumentError, 'render needs at least a graph' unless graph_index
399
380
  raise ArgumentError, 'render only works with a graph' unless rest == [nil, nil]
400
381
 
401
- annotator_options = {
382
+ pass_options = {
383
+ simplify_truffle_args: true,
402
384
  hide_frame_state: true,
385
+ hide_pi: true,
403
386
  hide_floating: false,
404
387
  reduce_edges: true
405
388
  }
@@ -420,12 +403,16 @@ module Seafoam
420
403
  raise ArgumentError, 'no list for --spotlight' unless spotlight_arg
421
404
 
422
405
  spotlight_nodes = spotlight_arg.split(',').map { |n| Integer(n) }
406
+ when '--full-truffle-args'
407
+ pass_options[:simplify_truffle_args] = false
423
408
  when '--show-frame-state'
424
- annotator_options[:hide_frame_state] = false
409
+ pass_options[:hide_frame_state] = false
410
+ when '--show-pi'
411
+ pass_options[:hide_pi] = false
425
412
  when '--hide-floating'
426
- annotator_options[:hide_floating] = true
413
+ pass_options[:hide_floating] = true
427
414
  when '--no-reduce-edges'
428
- annotator_options[:reduce_edges] = false
415
+ pass_options[:reduce_edges] = false
429
416
  when '--draw-blocks'
430
417
  draw_blocks = true
431
418
  when '--option'
@@ -436,7 +423,7 @@ module Seafoam
436
423
  raise ArgumentError, "no value for --option #{key}" unless out_file
437
424
 
438
425
  value = { 'true' => true, 'false' => 'false' }.fetch(key, value)
439
- annotator_options[key.to_sym] = value
426
+ pass_options[key.to_sym] = value
440
427
  else
441
428
  raise ArgumentError, "unexpected option #{arg}"
442
429
  end
@@ -459,7 +446,7 @@ module Seafoam
459
446
  with_graph(file, graph_index) do |parser|
460
447
  parser.skip_graph_header
461
448
  graph = parser.read_graph
462
- Annotators.apply graph, annotator_options
449
+ Passes.apply graph, pass_options
463
450
  if spotlight_nodes
464
451
  spotlight = Spotlight.new(graph)
465
452
  spotlight_nodes.each do |node_id|
@@ -569,6 +556,31 @@ module Seafoam
569
556
  raise ArgumentError, 'graph not found' unless graph_found
570
557
  end
571
558
 
559
+ # Prints help.
560
+ def help(*_args)
561
+ @out.puts 'seafoam file.bgv info'
562
+ @out.puts ' file.bgv list'
563
+ @out.puts ' file.bgv[:graph][:node[-edge]] search term...'
564
+ @out.puts ' file.bgv[:graph][:node[-edge]] edges'
565
+ @out.puts ' file.bgv[:graph][:node[-edge]] props'
566
+ @out.puts ' file.bgv:graph:node source'
567
+ @out.puts ' file.bgv:graph render'
568
+ @out.puts ' --spotlight n,n,n...'
569
+ @out.puts ' --out graph.pdf'
570
+ @out.puts ' graph.svg'
571
+ @out.puts ' graph.png'
572
+ @out.puts ' graph.dot'
573
+ @out.puts ' --full-truffle-args'
574
+ @out.puts ' --show-frame-state'
575
+ @out.puts ' --show-pi'
576
+ @out.puts ' --hide-floating'
577
+ @out.puts ' --no-reduce-edges'
578
+ @out.puts ' --draw-blocks'
579
+ @out.puts ' --option key value'
580
+ @out.puts ' --help'
581
+ @out.puts ' --version'
582
+ end
583
+
572
584
  # Prints the version.
573
585
  def version(*args)
574
586
  raise ArgumentError, "unexpected arguments #{args.join(' ')}" unless args.empty?
@@ -602,10 +614,15 @@ module Seafoam
602
614
 
603
615
  # Open a file for the user if possible.
604
616
  def autoopen(file)
605
- if RUBY_PLATFORM.include?('darwin') && @out.tty?
617
+ return unless @out.tty?
618
+
619
+ case RUBY_PLATFORM
620
+ when /darwin/
606
621
  system 'open', file
607
- # Don't worry if it fails.
622
+ when /linux/
623
+ system 'xdg-open', file
608
624
  end
625
+ # Don't worry if it fails.
609
626
  end
610
627
  end
611
628
  end
@@ -0,0 +1,18 @@
1
+ module Seafoam
2
+ module Graal
3
+ # Routines for understanding pi nodes in Graal.
4
+ module Pi
5
+ # Find the actual value behind potentially a chain of pi nodes.
6
+ def self.follow_pi_object(node)
7
+ node = node.edges.find { |edge| edge.props[:name] == 'object' }.from while PI_NODES.include?(node.props.dig(:node_class, :node_class))
8
+ node
9
+ end
10
+
11
+ # Pi nodes add type information.
12
+ PI_NODES = [
13
+ 'org.graalvm.compiler.nodes.PiNode',
14
+ 'org.graalvm.compiler.nodes.PiArrayNode'
15
+ ]
16
+ end
17
+ end
18
+ end
data/lib/seafoam/graph.rb CHANGED
@@ -2,13 +2,14 @@ module Seafoam
2
2
  # A graph, with properties, nodes, and edges. We don't encapsulate the graph
3
3
  # too much - be careful.
4
4
  class Graph
5
- attr_reader :props, :nodes, :edges, :blocks
5
+ attr_reader :props, :nodes, :edges, :blocks, :new_id
6
6
 
7
7
  def initialize(props = nil)
8
8
  @props = props || {}
9
9
  @nodes = {}
10
10
  @edges = []
11
11
  @blocks = []
12
+ @new_id = 0
12
13
  end
13
14
 
14
15
  # Create a node.
@@ -16,6 +17,7 @@ module Seafoam
16
17
  props ||= {}
17
18
  node = Node.new(id, props)
18
19
  @nodes[id] = node
20
+ @new_id = id + 1
19
21
  node
20
22
  end
21
23
 
@@ -36,6 +38,12 @@ module Seafoam
36
38
  @blocks.push block
37
39
  block
38
40
  end
41
+
42
+ def remove_edge(edge)
43
+ edge.from.outputs.delete edge
44
+ edge.to.inputs.delete edge
45
+ edges.delete edge
46
+ end
39
47
  end
40
48
 
41
49
  # A node, with properties, input edges, and output edges.
@@ -100,6 +100,9 @@ module Seafoam
100
100
  # from a shaded node.
101
101
  next if edge.to.props[:hidden] && edge.from.props[:spotlight] != 'shaded'
102
102
 
103
+ # Skip the edge if it's hidden itself
104
+ next if edge.props[:hidden]
105
+
103
106
  write_edge inline_attrs, edge
104
107
  end
105
108
  end
@@ -36,9 +36,7 @@ module Seafoam
36
36
  @out.puts JSON.pretty_generate(prepare_json(object))
37
37
  end
38
38
 
39
- private
40
-
41
- def prepare_json(object)
39
+ def self.prepare_json(object)
42
40
  case object
43
41
  when Float
44
42
  if object.nan?
@@ -1,15 +1,15 @@
1
1
  module Seafoam
2
- module Annotators
3
- # The fallback annotator always applies, and adds some basic annotations.
2
+ module Passes
3
+ # The fallback pass always applies, and adds some basic properties.
4
4
  # Works for example with Truffle AST and call graphs, but also means anyone
5
5
  # can emit a graph with 'label' properties and we can do something useful
6
6
  # with it.
7
- class FallbackAnnotator < Annotator
7
+ class FallbackPass < Pass
8
8
  def self.applies?(_graph)
9
9
  true
10
10
  end
11
11
 
12
- def annotate(graph)
12
+ def apply(graph)
13
13
  graph.nodes.each_value do |node|
14
14
  if node.props[:label].nil? && node.props['label']
15
15
  node.props[:label] = node.props['label']
@@ -1,18 +1,19 @@
1
1
  module Seafoam
2
- module Annotators
3
- # The Graal annotator applies if it looks like it was compiled by Graal or
2
+ module Passes
3
+ # The Graal pass applies if it looks like it was compiled by Graal or
4
4
  # Truffle.
5
- class GraalAnnotator < Annotator
5
+ class GraalPass < Pass
6
6
  def self.applies?(graph)
7
7
  graph.props.values.any? do |v|
8
8
  TRIGGERS.any? { |t| v.to_s.include?(t) }
9
9
  end
10
10
  end
11
11
 
12
- def annotate(graph)
13
- annotate_nodes graph
14
- annotate_edges graph
12
+ def apply(graph)
13
+ apply_nodes graph
14
+ apply_edges graph
15
15
  hide_frame_state graph if @options[:hide_frame_state]
16
+ hide_pi graph if @options[:hide_pi]
16
17
  hide_floating graph if @options[:hide_floating]
17
18
  reduce_edges graph if @options[:reduce_edges]
18
19
  hide_unused_nodes graph
@@ -21,8 +22,10 @@ module Seafoam
21
22
  private
22
23
 
23
24
  # Annotate nodes with their label and kind
24
- def annotate_nodes(graph)
25
+ def apply_nodes(graph)
25
26
  graph.nodes.each_value do |node|
27
+ next if node.props[:label]
28
+
26
29
  # The Java class of the node.
27
30
  node_class = node.props.dig(:node_class, :node_class)
28
31
 
@@ -93,6 +96,11 @@ module Seafoam
93
96
  name_template = 'π'
94
97
  end
95
98
 
99
+ # Use a symbol for PiArrayNode.
100
+ if node_class == 'org.graalvm.compiler.nodes.PiArrayNode'
101
+ name_template = '[π]'
102
+ end
103
+
96
104
  # Use a symbol for PhiNode.
97
105
  if node_class == 'org.graalvm.compiler.nodes.ValuePhiNode'
98
106
  name_template = 'ϕ'
@@ -208,7 +216,7 @@ module Seafoam
208
216
  end
209
217
 
210
218
  # Annotate edges with their label and kind.
211
- def annotate_edges(graph)
219
+ def apply_edges(graph)
212
220
  graph.edges.each do |edge|
213
221
  if edge.to.props.dig(:node_class, :node_class) == 'org.graalvm.compiler.nodes.ValuePhiNode' && edge.props[:name] == 'values'
214
222
  merge_node = edge.to.edges.find { |e| e.props[:name] == 'merge' }.from
@@ -311,6 +319,24 @@ module Seafoam
311
319
  end
312
320
  end
313
321
 
322
+ # Hide pi nodes - they add information for optimisation, but not generally
323
+ # useful day-to-day for understanding the graph. Connect the user to the
324
+ # actual object, which may be several steps away.
325
+ def hide_pi(graph)
326
+ loop do
327
+ umodified = true
328
+ graph.edges.each do |edge|
329
+ next unless Graal::Pi::PI_NODES.include?(edge.from.props.dig(:node_class, :node_class))
330
+
331
+ object = Graal::Pi.follow_pi_object(edge.from)
332
+ graph.create_edge object, edge.to, edge.props.merge({ synthetic: true })
333
+ graph.remove_edge edge
334
+ umodified = false
335
+ end
336
+ break if umodified
337
+ end
338
+ end
339
+
314
340
  # Hide floating nodes. This highlights just the control flow backbone.
315
341
  def hide_floating(graph)
316
342
  graph.nodes.each_value do |node|
@@ -332,15 +358,19 @@ module Seafoam
332
358
  end
333
359
  end
334
360
 
335
- # Hide nodes that have no non-hidden users and no control flow in. These
336
- # would display as a node floating unconnected to the rest of the graph
337
- # otherwise. An exception is made for node with an anchor edge coming in,
338
- # as some guards are anchored like this.
361
+ # Hide nodes that have no non-hidden users or edges and no control flow
362
+ # in. These would display as a node floating unconnected to the rest of
363
+ # the graph otherwise. An exception is made for node with an anchor edge
364
+ # coming in, as some guards are anchored like this.
339
365
  def hide_unused_nodes(graph)
340
366
  loop do
341
367
  modified = false
342
368
  graph.nodes.each_value do |node|
343
- next unless node.outputs.all? { |edge| edge.to.props[:hidden] } &&
369
+ # Call trees are like Graal graphs but don't have these edges -
370
+ # don't hide them.
371
+ next if node.props['truffleCallees']
372
+
373
+ next unless node.outputs.all? { |edge| edge.to.props[:hidden] || edge.props[:hidden] } &&
344
374
  node.inputs.none? { |edge| edge.props[:kind] == 'control' } &&
345
375
  node.inputs.none? { |edge| edge.props[:name] == 'anchor' }
346
376
 
@@ -0,0 +1,58 @@
1
+ module Seafoam
2
+ module Passes
3
+ # The Truffle pass applies if it looks like it was compiled by Truffle.
4
+ class TrufflePass < Pass
5
+ def self.applies?(graph)
6
+ graph.props.values.any? do |v|
7
+ TRIGGERS.any? { |t| v.to_s.include?(t) }
8
+ end
9
+ end
10
+
11
+ def apply(graph)
12
+ simplify_truffle_args graph if @options[:simplify_truffle_args]
13
+ end
14
+
15
+ private
16
+
17
+ # Simplify a Truffle argument load into a single, inlined, node very much
18
+ # like a Graal parameter node.
19
+ def simplify_truffle_args(graph)
20
+ graph.nodes.dup.each_value do |node|
21
+ next unless node.props.dig(:node_class, :node_class) == 'org.graalvm.compiler.nodes.java.LoadIndexedNode'
22
+
23
+ index_node = node.inputs.find { |edge| edge.props[:name] == 'index' }.from
24
+ array_node = Graal::Pi.follow_pi_object(node.inputs.find { |edge| edge.props[:name] == 'array' }.from)
25
+
26
+ next unless index_node.props.dig(:node_class, :node_class) == 'org.graalvm.compiler.nodes.ConstantNode'
27
+ next unless array_node.props.dig(:node_class, :node_class) == 'org.graalvm.compiler.nodes.ParameterNode'
28
+
29
+ node.props[:truffle_arg_load] = true
30
+
31
+ index = index_node.props['rawvalue']
32
+
33
+ arg_node = graph.create_node(graph.new_id, { synthetic: true, inlined: true, label: "T(#{index})", kind: 'input' })
34
+
35
+ node.outputs.each do |output|
36
+ next if output.props[:name] == 'next'
37
+
38
+ graph.create_edge arg_node, output.to, output.props.dup
39
+ graph.remove_edge output
40
+ end
41
+ end
42
+
43
+ graph.nodes.each_value.select { |node| node.props[:truffle_arg_load] }.each do |node|
44
+ control_in = node.inputs.find { |edge| edge.props[:name] == 'next' }
45
+ control_out = node.outputs.find { |edge| edge.props[:name] == 'next' }
46
+ graph.create_edge control_in.from, control_out.to, { name: 'next' }
47
+ graph.remove_edge control_in
48
+ graph.remove_edge control_out
49
+ end
50
+ end
51
+
52
+ # If we see these in the graph properties it's probably a Truffle graph.
53
+ TRIGGERS = %w[
54
+ TruffleCompiler
55
+ ]
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,61 @@
1
+ module Seafoam
2
+ # Passes are routines to read the graph and apply properties which tools,
3
+ # such as the render command, can use to show more understandable output.
4
+ module Passes
5
+ # Apply all applicable passes to a graph.
6
+ def self.apply(graph, options = {})
7
+ passes.each do |pass|
8
+ next unless pass.applies?(graph)
9
+
10
+ # Record for information that the pass was applied this graph.
11
+ passes_applied = graph.props[:passes_applied] ||= []
12
+ passes_applied.push pass
13
+
14
+ # Run the pass.
15
+ instance = pass.new(options)
16
+ instance.apply graph
17
+ end
18
+ end
19
+
20
+ # Get a list of all passes in the system.
21
+ def self.passes
22
+ # We have a defined order for passes to run - these passes at the start.
23
+ pre_passes = [
24
+ TrufflePass,
25
+ GraalPass
26
+ ]
27
+
28
+ # The fallback pass runs last.
29
+ post_passes = [
30
+ FallbackPass
31
+ ]
32
+
33
+ # Any extra passes in the middle.
34
+ extra_passes = Pass::SUBCLASSES.dup - pre_passes - post_passes
35
+
36
+ pre_passes + extra_passes + post_passes
37
+ end
38
+ end
39
+
40
+ # The base class for all passes. You must subclass this to be recognized
41
+ # as an pass.
42
+ class Pass
43
+ SUBCLASSES = []
44
+
45
+ def initialize(options = {})
46
+ @options = options
47
+ end
48
+
49
+ def applies?(_graph)
50
+ raise NotImplementedError
51
+ end
52
+
53
+ def apply(_graph)
54
+ raise NotImplementedError
55
+ end
56
+
57
+ def self.inherited(pass)
58
+ SUBCLASSES.push pass
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,5 @@
1
1
  module Seafoam
2
2
  MAJOR_VERSION = 0
3
- MINOR_VERSION = 8
3
+ MINOR_VERSION = 9
4
4
  VERSION = "#{MAJOR_VERSION}.#{MINOR_VERSION}"
5
5
  end
data/lib/seafoam.rb CHANGED
@@ -6,12 +6,13 @@ require 'seafoam/cfg/disassembler'
6
6
  require 'seafoam/colors'
7
7
  require 'seafoam/graph'
8
8
  require 'seafoam/graal/source'
9
- require 'seafoam/annotators'
10
- require 'seafoam/annotators/graal'
11
- require 'seafoam/annotators/fallback'
9
+ require 'seafoam/graal/pi'
10
+ require 'seafoam/passes'
11
+ require 'seafoam/passes/truffle'
12
+ require 'seafoam/passes/graal'
13
+ require 'seafoam/passes/fallback'
12
14
  require 'seafoam/spotlight'
13
15
  require 'seafoam/isabelle_writer'
14
16
  require 'seafoam/json_writer'
15
17
  require 'seafoam/graphviz_writer'
16
- require 'seafoam/config'
17
18
  require 'seafoam/commands'