seafoam 0.11 → 0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/bgv2isabelle +3 -2
- data/bin/bgv2json +3 -2
- data/bin/seafoam +3 -2
- data/lib/seafoam/bgv/bgv_parser.rb +58 -50
- data/lib/seafoam/binary/io_binary_reader.rb +19 -17
- data/lib/seafoam/colors.rb +17 -11
- data/lib/seafoam/commands.rb +210 -202
- data/lib/seafoam/formatters/base.rb +2 -0
- data/lib/seafoam/formatters/formatters.rb +5 -3
- data/lib/seafoam/formatters/json.rb +8 -5
- data/lib/seafoam/formatters/text.rb +7 -4
- data/lib/seafoam/graal/graph_description.rb +10 -3
- data/lib/seafoam/graal/pi.rb +10 -6
- data/lib/seafoam/graal/source.rb +13 -9
- data/lib/seafoam/graph.rb +15 -9
- data/lib/seafoam/graphviz_writer.rb +129 -99
- data/lib/seafoam/isabelle_writer.rb +9 -7
- data/lib/seafoam/json_writer.rb +17 -13
- data/lib/seafoam/markdown_writer.rb +18 -0
- data/lib/seafoam/mermaid_writer.rb +52 -0
- data/lib/seafoam/passes/fallback.rb +10 -6
- data/lib/seafoam/passes/graal.rb +189 -161
- data/lib/seafoam/passes/truffle.rb +120 -22
- data/lib/seafoam/passes.rb +36 -29
- data/lib/seafoam/spotlight.rb +4 -2
- data/lib/seafoam/version.rb +3 -1
- data/lib/seafoam.rb +22 -20
- metadata +9 -40
- data/bin/cfg2asm +0 -20
- data/lib/seafoam/cfg/cfg_parser.rb +0 -93
- data/lib/seafoam/cfg/disassembler.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44f9af9b54052ddbfc03bc99833eb0af6e2e5f2bd0a5612a77ea10e3d30b3fca
|
4
|
+
data.tar.gz: 7d1613577c3e033c69149eb51845540b88adc0c05bda3327c59a41c700647181
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f35b3f93409e92be806e793817461900f66d7d1a8e91e6ae95fc52f66fa61955d7c48f0de1899ad15b35e88fa2b6b4cbb70fed976accb9f20ee7725f201828fe
|
7
|
+
data.tar.gz: 03d4b654e6f2001128aa711ccddb4cccf09aed480d65578e0e49edb3d59c2acb5b594e3ef4f32b972e9821862aa24b9daa12c4fb7f1cef838a46c43c2c3b4fa9
|
data/bin/bgv2isabelle
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
+
require "seafoam"
|
4
5
|
|
5
6
|
# This is the 'bgv2isabelle' command line entry point.
|
6
7
|
|
@@ -15,6 +16,6 @@ rescue StandardError => e
|
|
15
16
|
raise e
|
16
17
|
else
|
17
18
|
# Otherwise, just print the message.
|
18
|
-
warn
|
19
|
+
warn("seafoam: #{e.message}")
|
19
20
|
end
|
20
21
|
end
|
data/bin/bgv2json
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
+
require "seafoam"
|
4
5
|
|
5
6
|
# This is the 'bgv2json' command line entry point.
|
6
7
|
|
@@ -15,6 +16,6 @@ rescue StandardError => e
|
|
15
16
|
raise e
|
16
17
|
else
|
17
18
|
# Otherwise, just print the message.
|
18
|
-
warn
|
19
|
+
warn("seafoam: #{e.message}")
|
19
20
|
end
|
20
21
|
end
|
data/bin/seafoam
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
+
require "seafoam"
|
4
5
|
|
5
6
|
# This is the 'seafoam' command line entry point.
|
6
7
|
|
@@ -15,6 +16,6 @@ rescue StandardError => e
|
|
15
16
|
raise e
|
16
17
|
else
|
17
18
|
# Otherwise, just print the message.
|
18
|
-
warn
|
19
|
+
warn("seafoam: #{e.message}")
|
19
20
|
end
|
20
21
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
require "zlib"
|
3
5
|
|
4
6
|
module Seafoam
|
5
7
|
module BGV
|
@@ -21,7 +23,7 @@ module Seafoam
|
|
21
23
|
|
22
24
|
# Read the file header and return the version.
|
23
25
|
def read_file_header(version_check: true)
|
24
|
-
raise EncodingError,
|
26
|
+
raise EncodingError, "does not appear to be a BGV file - missing header" unless @reader.read_bytes(4) == MAGIC
|
25
27
|
|
26
28
|
@major = @reader.read_sint8
|
27
29
|
@minor = @reader.read_sint8
|
@@ -90,7 +92,7 @@ module Seafoam
|
|
90
92
|
group: @group_stack.dup,
|
91
93
|
format: format,
|
92
94
|
args: args,
|
93
|
-
props: props
|
95
|
+
props: props,
|
94
96
|
}
|
95
97
|
end
|
96
98
|
|
@@ -115,15 +117,17 @@ module Seafoam
|
|
115
117
|
node = edge[:node]
|
116
118
|
props = edge[:edge]
|
117
119
|
inputs = edge[:inputs]
|
118
|
-
others = edge[:ids].reject(&:nil?).map
|
120
|
+
others = edge[:ids].reject(&:nil?).map do |id|
|
121
|
+
graph.nodes[id] || raise(EncodingError, "BGV edge with unknown node #{id}")
|
122
|
+
end
|
119
123
|
others.each_with_index do |other, index|
|
120
124
|
# We need to give each edge their own property as they're annotated separately.
|
121
125
|
props = props.dup
|
122
126
|
props[:index] = index
|
123
127
|
if inputs
|
124
|
-
graph.create_edge
|
128
|
+
graph.create_edge(other, node, props)
|
125
129
|
else
|
126
|
-
graph.create_edge
|
130
|
+
graph.create_edge(node, other, props)
|
127
131
|
end
|
128
132
|
end
|
129
133
|
end
|
@@ -134,7 +138,7 @@ module Seafoam
|
|
134
138
|
block_nodes = @reader.read_sint32.times.map { @reader.read_sint32 }
|
135
139
|
# Followers aren't used but could be.
|
136
140
|
@reader.read_sint32.times.map { @reader.read_sint32 }
|
137
|
-
graph.create_block
|
141
|
+
graph.create_block(block_id, block_nodes)
|
138
142
|
end
|
139
143
|
graph
|
140
144
|
end
|
@@ -147,8 +151,8 @@ module Seafoam
|
|
147
151
|
node_class = read_pool_object
|
148
152
|
skip_bool
|
149
153
|
skip_props
|
150
|
-
skip_edges
|
151
|
-
skip_edges
|
154
|
+
skip_edges(node_class, true)
|
155
|
+
skip_edges(node_class, false)
|
152
156
|
end
|
153
157
|
skip_blocks
|
154
158
|
end
|
@@ -200,9 +204,9 @@ module Seafoam
|
|
200
204
|
short_name: short_name,
|
201
205
|
method: method,
|
202
206
|
bci: bci,
|
203
|
-
props: props
|
207
|
+
props: props,
|
204
208
|
}
|
205
|
-
@group_stack.push
|
209
|
+
@group_stack.push(group)
|
206
210
|
end
|
207
211
|
|
208
212
|
# Read the closing of a group.
|
@@ -228,16 +232,16 @@ module Seafoam
|
|
228
232
|
# Skip over edges.
|
229
233
|
def skip_edges(node_class, inputs)
|
230
234
|
edges = if inputs
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
+
node_class[:inputs]
|
236
|
+
else
|
237
|
+
node_class[:outputs]
|
238
|
+
end
|
235
239
|
edges.each do |edge|
|
236
240
|
count = if edge[:direct]
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
+
1
|
242
|
+
else
|
243
|
+
@reader.read_sint16
|
244
|
+
end
|
241
245
|
count.times do
|
242
246
|
@reader.skip_int32
|
243
247
|
end
|
@@ -247,16 +251,16 @@ module Seafoam
|
|
247
251
|
# Read edges, producing an array of edge hashes.
|
248
252
|
def read_edges(node, node_class, inputs)
|
249
253
|
edges = if inputs
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
+
node_class[:inputs]
|
255
|
+
else
|
256
|
+
node_class[:outputs]
|
257
|
+
end
|
254
258
|
edges.map do |edge|
|
255
259
|
count = if edge[:direct]
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
+
1
|
261
|
+
else
|
262
|
+
@reader.read_sint16
|
263
|
+
end
|
260
264
|
ids = count.times.map do
|
261
265
|
id = @reader.read_sint32
|
262
266
|
raise if id < -1
|
@@ -268,7 +272,7 @@ module Seafoam
|
|
268
272
|
node: node,
|
269
273
|
edge: edge,
|
270
274
|
ids: ids,
|
271
|
-
inputs: inputs
|
275
|
+
inputs: inputs,
|
272
276
|
}
|
273
277
|
end
|
274
278
|
end
|
@@ -277,8 +281,8 @@ module Seafoam
|
|
277
281
|
def skip_blocks
|
278
282
|
@reader.read_sint32.times do
|
279
283
|
@reader.skip_int32
|
280
|
-
@reader.skip_int32
|
281
|
-
@reader.skip_int32
|
284
|
+
@reader.skip_int32(@reader.read_sint32)
|
285
|
+
@reader.skip_int32(@reader.read_sint32)
|
282
286
|
end
|
283
287
|
end
|
284
288
|
|
@@ -323,9 +327,9 @@ module Seafoam
|
|
323
327
|
skip_pool_object
|
324
328
|
end
|
325
329
|
when PROPERTY_INT
|
326
|
-
@reader.skip_int32
|
330
|
+
@reader.skip_int32(@reader.read_sint32)
|
327
331
|
when PROPERTY_DOUBLE
|
328
|
-
@reader.skip_float64
|
332
|
+
@reader.skip_float64(@reader.read_sint32)
|
329
333
|
else
|
330
334
|
raise EncodingError, "unknown BGV property array type 0x#{type.to_s(16)}"
|
331
335
|
end
|
@@ -388,7 +392,8 @@ module Seafoam
|
|
388
392
|
when POOL_NULL
|
389
393
|
when POOL_NEW
|
390
394
|
read_pool_entry
|
391
|
-
when POOL_STRING, POOL_ENUM, POOL_CLASS, POOL_METHOD, POOL_NODE_CLASS,
|
395
|
+
when POOL_STRING, POOL_ENUM, POOL_CLASS, POOL_METHOD, POOL_NODE_CLASS,
|
396
|
+
POOL_FIELD, POOL_SIGNATURE, POOL_NODE_SOURCE_POSITION, POOL_NODE
|
392
397
|
@reader.skip_int16
|
393
398
|
else
|
394
399
|
raise EncodingError, "unknown token 0x#{token.to_s(16)} in BGV pool object"
|
@@ -403,7 +408,8 @@ module Seafoam
|
|
403
408
|
nil
|
404
409
|
when POOL_NEW
|
405
410
|
read_pool_entry
|
406
|
-
when POOL_STRING, POOL_ENUM, POOL_CLASS, POOL_METHOD, POOL_NODE_CLASS,
|
411
|
+
when POOL_STRING, POOL_ENUM, POOL_CLASS, POOL_METHOD, POOL_NODE_CLASS,
|
412
|
+
POOL_FIELD, POOL_SIGNATURE, POOL_NODE_SOURCE_POSITION, POOL_NODE
|
407
413
|
id = @reader.read_uint16
|
408
414
|
object = @pool[id]
|
409
415
|
raise EncodingError, "unknown BGV pool object #{token}" unless object
|
@@ -425,7 +431,9 @@ module Seafoam
|
|
425
431
|
when POOL_ENUM
|
426
432
|
enum_class = read_pool_object
|
427
433
|
enum_ordinal = @reader.read_sint32
|
428
|
-
|
434
|
+
if enum_ordinal.negative? || enum_ordinal >= enum_class.size
|
435
|
+
raise EncodingError, "unknown BGV eum ordinal #{enum_ordinal} in #{enum_class}"
|
436
|
+
end
|
429
437
|
|
430
438
|
object = enum_class[enum_ordinal]
|
431
439
|
when POOL_CLASS
|
@@ -448,12 +456,12 @@ module Seafoam
|
|
448
456
|
signature = read_pool_object
|
449
457
|
modifiers = @reader.read_sint32
|
450
458
|
bytes_length = @reader.read_sint32
|
451
|
-
@reader.skip
|
459
|
+
@reader.skip(bytes_length) if bytes_length != -1
|
452
460
|
object = {
|
453
461
|
declaring_class: declaring_class,
|
454
462
|
method_name: method_name,
|
455
463
|
signature: signature,
|
456
|
-
modifiers: modifiers
|
464
|
+
modifiers: modifiers,
|
457
465
|
}
|
458
466
|
when POOL_NODE_CLASS
|
459
467
|
node_class = read_pool_object
|
@@ -464,7 +472,7 @@ module Seafoam
|
|
464
472
|
node_class: node_class,
|
465
473
|
name_template: name_template,
|
466
474
|
inputs: inputs,
|
467
|
-
outputs: outputs
|
475
|
+
outputs: outputs,
|
468
476
|
}
|
469
477
|
when POOL_FIELD
|
470
478
|
field_class = read_pool_object
|
@@ -475,7 +483,7 @@ module Seafoam
|
|
475
483
|
field_class: field_class,
|
476
484
|
name: name,
|
477
485
|
type_name: type_name,
|
478
|
-
modifiers: modifiers
|
486
|
+
modifiers: modifiers,
|
479
487
|
}
|
480
488
|
when POOL_SIGNATURE
|
481
489
|
args = @reader.read_sint16.times.map do
|
@@ -484,7 +492,7 @@ module Seafoam
|
|
484
492
|
ret = read_pool_object
|
485
493
|
object = {
|
486
494
|
args: args,
|
487
|
-
ret: ret
|
495
|
+
ret: ret,
|
488
496
|
}
|
489
497
|
when POOL_NODE_SOURCE_POSITION
|
490
498
|
method = read_pool_object
|
@@ -498,26 +506,26 @@ module Seafoam
|
|
498
506
|
loc_line = @reader.read_sint32
|
499
507
|
loc_start = @reader.read_sint32
|
500
508
|
loc_end = @reader.read_sint32
|
501
|
-
locs.push
|
509
|
+
locs.push([location, loc_line, loc_start, loc_end])
|
502
510
|
end
|
503
511
|
caller = read_pool_object
|
504
512
|
object = {
|
505
513
|
method: method,
|
506
514
|
bci: bci,
|
507
515
|
locs: locs,
|
508
|
-
caller: caller
|
516
|
+
caller: caller,
|
509
517
|
}
|
510
518
|
when POOL_NODE
|
511
519
|
node_id = @reader.read_sint32
|
512
520
|
node_class = read_pool_object
|
513
521
|
object = {
|
514
522
|
node_id: node_id,
|
515
|
-
node_class: node_class
|
523
|
+
node_class: node_class,
|
516
524
|
}
|
517
525
|
else
|
518
526
|
raise EncodingError, "unknown BGV pool type 0x#{type.to_s(16)}"
|
519
527
|
end
|
520
|
-
set_pool_entry
|
528
|
+
set_pool_entry(id, object)
|
521
529
|
end
|
522
530
|
|
523
531
|
# Hook method that can be overidden for debugging.
|
@@ -534,7 +542,7 @@ module Seafoam
|
|
534
542
|
{
|
535
543
|
direct: !indirect,
|
536
544
|
name: name,
|
537
|
-
type: type
|
545
|
+
type: type,
|
538
546
|
}
|
539
547
|
end
|
540
548
|
end
|
@@ -542,7 +550,7 @@ module Seafoam
|
|
542
550
|
# Skip over a UTF-8 string.
|
543
551
|
def skip_string
|
544
552
|
length = @reader.read_sint32
|
545
|
-
@reader.skip
|
553
|
+
@reader.skip(length) if length != -1
|
546
554
|
end
|
547
555
|
|
548
556
|
# Read a UTF-8 string.
|
@@ -552,7 +560,7 @@ module Seafoam
|
|
552
560
|
nil
|
553
561
|
else
|
554
562
|
string = @reader.read_utf8(length)
|
555
|
-
raise EncodingError,
|
563
|
+
raise EncodingError, "null byte in BGV string" if string.include?("\0")
|
556
564
|
|
557
565
|
string
|
558
566
|
end
|
@@ -578,11 +586,11 @@ module Seafoam
|
|
578
586
|
|
579
587
|
# File format constants.
|
580
588
|
|
581
|
-
MAGIC =
|
589
|
+
MAGIC = "BIGV"
|
582
590
|
|
583
591
|
SUPPORTED_VERSIONS = [
|
584
592
|
[6, 1],
|
585
|
-
[7, 0]
|
593
|
+
[7, 0],
|
586
594
|
]
|
587
595
|
|
588
596
|
BEGIN_GROUP = 0x00
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Seafoam
|
2
4
|
module Binary
|
3
5
|
# An adapter to read binary values from an IO stream.
|
@@ -7,7 +9,7 @@ module Seafoam
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def read_utf8(length)
|
10
|
-
read_bytes(length).force_encoding
|
12
|
+
read_bytes(length).force_encoding(Encoding::UTF_8)
|
11
13
|
end
|
12
14
|
|
13
15
|
def read_bytes(length)
|
@@ -15,31 +17,31 @@ module Seafoam
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def read_float64
|
18
|
-
@io.read(8).unpack1(
|
20
|
+
@io.read(8).unpack1("G")
|
19
21
|
end
|
20
22
|
|
21
23
|
def read_float32
|
22
|
-
@io.read(4).unpack1(
|
24
|
+
@io.read(4).unpack1("g")
|
23
25
|
end
|
24
26
|
|
25
27
|
def read_sint64
|
26
|
-
@io.read(8).unpack1(
|
28
|
+
@io.read(8).unpack1("q>")
|
27
29
|
end
|
28
30
|
|
29
31
|
def read_sint32
|
30
|
-
@io.read(4).unpack1(
|
32
|
+
@io.read(4).unpack1("l>")
|
31
33
|
end
|
32
34
|
|
33
35
|
def read_sint16
|
34
|
-
@io.read(2).unpack1(
|
36
|
+
@io.read(2).unpack1("s>")
|
35
37
|
end
|
36
38
|
|
37
39
|
def read_uint16
|
38
|
-
@io.read(2).unpack1(
|
40
|
+
@io.read(2).unpack1("S>")
|
39
41
|
end
|
40
42
|
|
41
43
|
def read_sint8
|
42
|
-
@io.read(1).unpack1(
|
44
|
+
@io.read(1).unpack1("c")
|
43
45
|
end
|
44
46
|
|
45
47
|
def read_uint8
|
@@ -47,37 +49,37 @@ module Seafoam
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def peek_sint8
|
50
|
-
byte = @io.read(1).unpack1(
|
51
|
-
@io.ungetbyte
|
52
|
+
byte = @io.read(1).unpack1("c")
|
53
|
+
@io.ungetbyte(byte)
|
52
54
|
byte
|
53
55
|
end
|
54
56
|
|
55
57
|
def skip_float64(count = 1)
|
56
|
-
skip
|
58
|
+
skip(count * 8)
|
57
59
|
end
|
58
60
|
|
59
61
|
def skip_float32(count = 1)
|
60
|
-
skip
|
62
|
+
skip(count * 4)
|
61
63
|
end
|
62
64
|
|
63
65
|
def skip_int64(count = 1)
|
64
|
-
skip
|
66
|
+
skip(count * 8)
|
65
67
|
end
|
66
68
|
|
67
69
|
def skip_int32(count = 1)
|
68
|
-
skip
|
70
|
+
skip(count * 4)
|
69
71
|
end
|
70
72
|
|
71
73
|
def skip_int16(count = 1)
|
72
|
-
skip
|
74
|
+
skip(count * 2)
|
73
75
|
end
|
74
76
|
|
75
77
|
def skip_int8(count = 1)
|
76
|
-
skip
|
78
|
+
skip(count)
|
77
79
|
end
|
78
80
|
|
79
81
|
def skip(count)
|
80
|
-
@io.seek
|
82
|
+
@io.seek(count, IO::SEEK_CUR)
|
81
83
|
end
|
82
84
|
|
83
85
|
def eof?
|
data/lib/seafoam/colors.rb
CHANGED
@@ -1,18 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Seafoam
|
2
4
|
# Colors from and derived from the TruffleRuby logo.
|
3
5
|
|
4
6
|
# TruffleRuby logo Copyright (C) 2017 Talkdesk, Inc.
|
5
7
|
# Licensed under CC BY 4.0: https://creativecommons.org/licenses/by/4.0/
|
6
8
|
|
7
|
-
WHITE_ICE =
|
8
|
-
CRUISE =
|
9
|
-
KEPPEL =
|
10
|
-
CARISSMA =
|
11
|
-
AMARANTH =
|
12
|
-
BLACK =
|
13
|
-
WHITE =
|
14
|
-
DUST =
|
15
|
-
BIG_STONE =
|
16
|
-
ICE_STONE =
|
17
|
-
ORANGE =
|
9
|
+
WHITE_ICE = "#d7ede7"
|
10
|
+
CRUISE = "#b8ddd1"
|
11
|
+
KEPPEL = "#3cb4a4"
|
12
|
+
CARISSMA = "#e98693"
|
13
|
+
AMARANTH = "#da2d4f"
|
14
|
+
BLACK = "#1a1919"
|
15
|
+
WHITE = "#ffffff"
|
16
|
+
DUST = "#f9f9f9"
|
17
|
+
BIG_STONE = "#343d46"
|
18
|
+
ICE_STONE = "#b3bbc3"
|
19
|
+
ORANGE = "#ffa500"
|
20
|
+
LIGHT_BLUE = "#ccccff"
|
21
|
+
LIGHT_PURPLE = "#c39bd3"
|
22
|
+
LIGHT_YELLOW = "#ffffde"
|
23
|
+
DARK_YELLOW = "#aaaa33"
|
18
24
|
end
|