furnace 0.4.0.beta.1 → 0.4.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +6 -0
- data/INSTRUMENT.md +250 -0
- data/Rakefile +1 -1
- data/lib/furnace.rb +10 -6
- data/lib/furnace/ast/node.rb +15 -1
- data/lib/furnace/awesome_printer.rb +121 -0
- data/lib/furnace/context.rb +0 -0
- data/lib/furnace/ssa.rb +7 -25
- data/lib/furnace/ssa/argument.rb +14 -10
- data/lib/furnace/ssa/basic_block.rb +70 -25
- data/lib/furnace/ssa/builder.rb +11 -7
- data/lib/furnace/ssa/constant.rb +19 -11
- data/lib/furnace/ssa/event_stream.rb +145 -0
- data/lib/furnace/ssa/function.rb +78 -57
- data/lib/furnace/ssa/generic_instruction.rb +12 -5
- data/lib/furnace/ssa/instruction.rb +50 -35
- data/lib/furnace/ssa/instruction_syntax.rb +9 -25
- data/lib/furnace/ssa/instructions/branch.rb +2 -2
- data/lib/furnace/ssa/instructions/phi.rb +12 -10
- data/lib/furnace/ssa/instructions/return.rb +3 -3
- data/lib/furnace/ssa/instructions/return_value.rb +11 -0
- data/lib/furnace/ssa/instrumentation.rb +33 -0
- data/lib/furnace/ssa/module.rb +5 -1
- data/lib/furnace/ssa/named_value.rb +31 -10
- data/lib/furnace/ssa/terminator_instruction.rb +6 -6
- data/lib/furnace/ssa/types/basic_block.rb +4 -8
- data/lib/furnace/ssa/types/function.rb +4 -8
- data/lib/furnace/ssa/user.rb +14 -15
- data/lib/furnace/ssa/value.rb +9 -5
- data/lib/furnace/transform/iterative.rb +20 -4
- data/lib/furnace/type.rb +9 -0
- data/lib/furnace/type/bottom.rb +11 -0
- data/lib/furnace/type/top.rb +72 -0
- data/lib/furnace/type/value.rb +13 -0
- data/lib/furnace/type/variable.rb +61 -0
- data/lib/furnace/version.rb +1 -1
- data/test/{test_helper.rb → helper.rb} +28 -3
- data/test/{ast_test.rb → test_ast.rb} +13 -1
- data/test/test_awesome_printer.rb +148 -0
- data/test/{ssa_test.rb → test_ssa.rb} +276 -315
- data/test/{transform_test.rb → test_transform.rb} +2 -2
- data/test/test_type.rb +138 -0
- metadata +83 -105
- data/lib/furnace/graphviz.rb +0 -49
- data/lib/furnace/ssa/generic_type.rb +0 -16
- data/lib/furnace/ssa/pretty_printer.rb +0 -113
- data/lib/furnace/ssa/type.rb +0 -27
- data/lib/furnace/ssa/types/void.rb +0 -15
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 09c880a785045b6520d037457d92d4c1fb5a5252
|
4
|
+
data.tar.gz: 95fe046fd5ae819eca7bc005230e688c7be97647
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 432ac773720df277c3c0b8d834f9364176d5245cd84027c1d775a39d05f0107aff5b6bdfbd9fde5df8a2a886ef4db7c9a0a9e9a8f530ad9a3b3152b65317b801
|
7
|
+
data.tar.gz: fff823fe2cf09c881a6e827aa160ba8491e25e33d9dc38c4f8053975410290f293020b09d474c3bb9d76875056947e457fe7e886ae72af7b878a95463d336492
|
data/.travis.yml
CHANGED
data/INSTRUMENT.md
ADDED
@@ -0,0 +1,250 @@
|
|
1
|
+
Insturmentation stream format
|
2
|
+
=============================
|
3
|
+
|
4
|
+
Instrumentation data is produced by Foundry as streams of events dumped
|
5
|
+
as JSON. A stream corresponds to one function.
|
6
|
+
|
7
|
+
Within a function, entities have names. Entity names are always unique.
|
8
|
+
Entity names may change; in this case, all subsequent references are to be
|
9
|
+
resolved via updated name.
|
10
|
+
|
11
|
+
Entities may refer to types. Types are identified with a number, which is
|
12
|
+
always unique and does not change.
|
13
|
+
|
14
|
+
The root of the stream contains a Function.
|
15
|
+
|
16
|
+
Type
|
17
|
+
----
|
18
|
+
|
19
|
+
There are several kinds of Types, disambiguated by the field "kind".
|
20
|
+
|
21
|
+
### Void type
|
22
|
+
|
23
|
+
{
|
24
|
+
"event": "type",
|
25
|
+
"id": <number>,
|
26
|
+
"kind": "void",
|
27
|
+
}
|
28
|
+
|
29
|
+
Should render as:
|
30
|
+
|
31
|
+
void
|
32
|
+
|
33
|
+
### Monotypes
|
34
|
+
|
35
|
+
{
|
36
|
+
"event": "type",
|
37
|
+
"id": <number>,
|
38
|
+
"kind": "monotype",
|
39
|
+
"name": <string>
|
40
|
+
}
|
41
|
+
|
42
|
+
Should render as:
|
43
|
+
|
44
|
+
#{name}
|
45
|
+
|
46
|
+
### Parametric types
|
47
|
+
|
48
|
+
{
|
49
|
+
"event": "type",
|
50
|
+
"id": <number>,
|
51
|
+
"kind": "parametric",
|
52
|
+
"name": <string>,
|
53
|
+
"parameters": <array of Type>
|
54
|
+
}
|
55
|
+
|
56
|
+
Should render as:
|
57
|
+
|
58
|
+
#{name}<#{parameters.map(&:render)}>
|
59
|
+
|
60
|
+
Function
|
61
|
+
--------
|
62
|
+
|
63
|
+
{
|
64
|
+
"name": <string>,
|
65
|
+
"present": <Boolean>,
|
66
|
+
"events": <array of Event>
|
67
|
+
}
|
68
|
+
|
69
|
+
### Set arguments
|
70
|
+
|
71
|
+
{
|
72
|
+
"event": "set_arguments",
|
73
|
+
"arguments": <array of Argument>
|
74
|
+
}
|
75
|
+
|
76
|
+
### Set return type
|
77
|
+
|
78
|
+
{
|
79
|
+
"event": "set_return_type",
|
80
|
+
"return_type": <Type>
|
81
|
+
}
|
82
|
+
|
83
|
+
Argument
|
84
|
+
--------
|
85
|
+
|
86
|
+
{
|
87
|
+
"name": <string>,
|
88
|
+
"type": <Type>
|
89
|
+
}
|
90
|
+
|
91
|
+
Should render as:
|
92
|
+
|
93
|
+
#{type} %#{name}
|
94
|
+
|
95
|
+
Basic block
|
96
|
+
-----------
|
97
|
+
|
98
|
+
Should render as:
|
99
|
+
|
100
|
+
#{name}:
|
101
|
+
#{instructions.map(&:render)}
|
102
|
+
|
103
|
+
### Add basic block
|
104
|
+
|
105
|
+
{
|
106
|
+
"event": "add_basic_block",
|
107
|
+
"name": <string>
|
108
|
+
}
|
109
|
+
|
110
|
+
### Remove basic block
|
111
|
+
|
112
|
+
{
|
113
|
+
"event": "remove_basic_block",
|
114
|
+
"name": <string>
|
115
|
+
}
|
116
|
+
|
117
|
+
### Rename basic block
|
118
|
+
|
119
|
+
{
|
120
|
+
"event": "rename_basic_block",
|
121
|
+
"name": <string>,
|
122
|
+
"new_name": <string>
|
123
|
+
}
|
124
|
+
|
125
|
+
Operand
|
126
|
+
-------
|
127
|
+
|
128
|
+
### Constant operand
|
129
|
+
|
130
|
+
{
|
131
|
+
"kind": "constant",
|
132
|
+
"type": <Type>,
|
133
|
+
"value": <string>
|
134
|
+
}
|
135
|
+
|
136
|
+
Should render as:
|
137
|
+
|
138
|
+
#{type} #{value}
|
139
|
+
|
140
|
+
### Argument operand
|
141
|
+
|
142
|
+
{
|
143
|
+
"kind": "argument",
|
144
|
+
"name": <string>
|
145
|
+
}
|
146
|
+
|
147
|
+
Should render as:
|
148
|
+
|
149
|
+
%#{name}
|
150
|
+
|
151
|
+
### Instruction operand
|
152
|
+
|
153
|
+
{
|
154
|
+
"kind": "instruction",
|
155
|
+
"name": <string>
|
156
|
+
}
|
157
|
+
|
158
|
+
Should render as:
|
159
|
+
|
160
|
+
%#{name}
|
161
|
+
|
162
|
+
### Basic block operand
|
163
|
+
|
164
|
+
{
|
165
|
+
"kind": "basic_block",
|
166
|
+
"name": <string>
|
167
|
+
}
|
168
|
+
|
169
|
+
Should render as:
|
170
|
+
|
171
|
+
label %#{name}
|
172
|
+
|
173
|
+
Presence of an operand of this type should create an edge in the graph.
|
174
|
+
|
175
|
+
### Function operand
|
176
|
+
|
177
|
+
{
|
178
|
+
"kind": "function",
|
179
|
+
"name": <string>
|
180
|
+
}
|
181
|
+
|
182
|
+
Should render as:
|
183
|
+
|
184
|
+
function "#{name}"
|
185
|
+
|
186
|
+
Presence of an operand of this type should create a cross-reference link.
|
187
|
+
|
188
|
+
Instruction
|
189
|
+
-----------
|
190
|
+
|
191
|
+
Should render as:
|
192
|
+
|
193
|
+
1. If it has non-void type:
|
194
|
+
|
195
|
+
#{type} %#{name} = #{opcode} #{parameters} #{operands}
|
196
|
+
|
197
|
+
2. If it has void type:
|
198
|
+
|
199
|
+
#{opcode} #{parameters} #{operands}
|
200
|
+
|
201
|
+
If `opcode` is `phi`, render `operands` comma-separated with each operand as:
|
202
|
+
|
203
|
+
#{operand[0]} => #{operand[1]}
|
204
|
+
|
205
|
+
Else, render `operands` as comma-separated operands.
|
206
|
+
|
207
|
+
### Add instruction
|
208
|
+
|
209
|
+
{
|
210
|
+
"event": "add_instruction",
|
211
|
+
"name": <string>,
|
212
|
+
"basic_block": <string>,
|
213
|
+
"position": <number>
|
214
|
+
}
|
215
|
+
|
216
|
+
### Update instruction
|
217
|
+
|
218
|
+
{
|
219
|
+
"event": "update_instruction",
|
220
|
+
"opcode": <string>,
|
221
|
+
"name": <string>
|
222
|
+
"parameters": <string>
|
223
|
+
"operands": <array>
|
224
|
+
"type": <Type>
|
225
|
+
}
|
226
|
+
|
227
|
+
### Remove instruction
|
228
|
+
|
229
|
+
{
|
230
|
+
"event": "remove_instruction",
|
231
|
+
"name": <string>
|
232
|
+
}
|
233
|
+
|
234
|
+
### Rename instruction
|
235
|
+
|
236
|
+
{
|
237
|
+
"event": "rename_instruction",
|
238
|
+
"name": <string>,
|
239
|
+
"new_name": <string>
|
240
|
+
}
|
241
|
+
|
242
|
+
Miscellanea
|
243
|
+
-----------
|
244
|
+
|
245
|
+
### Transformation start
|
246
|
+
|
247
|
+
{
|
248
|
+
"event": "transform_start",
|
249
|
+
"name": <string>
|
250
|
+
}
|
data/Rakefile
CHANGED
data/lib/furnace.rb
CHANGED
@@ -2,22 +2,26 @@
|
|
2
2
|
# static analyzers--any programs which read, manipulate or transform
|
3
3
|
# other programs.
|
4
4
|
#
|
5
|
-
# Currently it provides
|
6
|
-
#
|
5
|
+
# Currently it provides four loosely coupled modules, each operating
|
6
|
+
# upon a single kind of entity:
|
7
7
|
#
|
8
8
|
# * Abstract syntax trees: {AST}
|
9
|
+
# * Parametric types: {Type}
|
9
10
|
# * Static single assignment representation: {SSA}
|
10
11
|
# * Transformations: {Transform}
|
11
12
|
#
|
12
|
-
# Additionally, a
|
13
|
+
# Additionally, a custom pretty printing module {AwesomePrinter} is
|
14
|
+
# provided which has built-in knowledge of {Type}s.
|
15
|
+
#
|
13
16
|
module Furnace
|
14
17
|
require "furnace/version"
|
15
18
|
|
19
|
+
require "furnace/awesome_printer"
|
20
|
+
|
16
21
|
require "furnace/ast"
|
22
|
+
require "furnace/type"
|
17
23
|
require "furnace/ssa"
|
18
24
|
|
19
25
|
require "furnace/transform/pipeline"
|
20
26
|
require "furnace/transform/iterative"
|
21
|
-
|
22
|
-
require "furnace/graphviz"
|
23
|
-
end
|
27
|
+
end
|
data/lib/furnace/ast/node.rb
CHANGED
@@ -123,6 +123,20 @@ module Furnace::AST
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
+
# Concatenates `array` with `children` and returns the resulting node.
|
127
|
+
#
|
128
|
+
# @return [AST::Node]
|
129
|
+
def +(array)
|
130
|
+
updated(nil, @children + array.to_a)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Appends `element` to `children` and returns the resulting node.
|
134
|
+
#
|
135
|
+
# @return [AST::Node]
|
136
|
+
def <<(element)
|
137
|
+
updated(nil, @children + [element])
|
138
|
+
end
|
139
|
+
|
126
140
|
# Converts `self` to a concise s-expression, omitting any children.
|
127
141
|
#
|
128
142
|
# @return [String]
|
@@ -198,4 +212,4 @@ module Furnace::AST
|
|
198
212
|
@type.to_s.gsub('_', '-')
|
199
213
|
end
|
200
214
|
end
|
201
|
-
end
|
215
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'ansi'
|
2
|
+
|
3
|
+
module Furnace
|
4
|
+
class AwesomePrinter
|
5
|
+
@colorize = true
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_accessor :colorize
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(colorize=self.class.colorize,
|
12
|
+
annotator=Type::Variable::Annotator.new)
|
13
|
+
@colorize = colorize
|
14
|
+
@annotator = annotator
|
15
|
+
|
16
|
+
@buffer = ""
|
17
|
+
@need_space = false
|
18
|
+
|
19
|
+
yield self if block_given?
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
@buffer
|
24
|
+
end
|
25
|
+
|
26
|
+
alias to_str to_s
|
27
|
+
|
28
|
+
def ==(other)
|
29
|
+
to_s == other
|
30
|
+
end
|
31
|
+
|
32
|
+
def =~(other)
|
33
|
+
to_s =~ other
|
34
|
+
end
|
35
|
+
|
36
|
+
def append(what)
|
37
|
+
@need_space = false
|
38
|
+
@buffer << what.to_s
|
39
|
+
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def text(what)
|
44
|
+
ensure_space { append what }
|
45
|
+
end
|
46
|
+
|
47
|
+
def newline
|
48
|
+
append "\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
def nest(what, &block)
|
52
|
+
if what
|
53
|
+
if what.respond_to? :awesome_print
|
54
|
+
what.awesome_print(self)
|
55
|
+
else
|
56
|
+
text what.to_s
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def name(what)
|
64
|
+
text "%#{what}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def type(what)
|
68
|
+
text with_ansi(:green) { what }
|
69
|
+
end
|
70
|
+
|
71
|
+
def type_variable(what)
|
72
|
+
text with_ansi(:bright, :magenta) { "~#{@annotator.annotate(what)}" }
|
73
|
+
end
|
74
|
+
|
75
|
+
def keyword(what)
|
76
|
+
text with_ansi(:bright, :white) { what }
|
77
|
+
end
|
78
|
+
|
79
|
+
def collection(left='', separator='', right='', what, &block)
|
80
|
+
return self if what.empty?
|
81
|
+
|
82
|
+
ensure_space do
|
83
|
+
append left
|
84
|
+
|
85
|
+
what.each.with_index do |element, index|
|
86
|
+
if index > 0
|
87
|
+
append separator
|
88
|
+
end
|
89
|
+
|
90
|
+
if block_given?
|
91
|
+
yield element
|
92
|
+
else
|
93
|
+
nest element
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
append right
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
protected
|
102
|
+
|
103
|
+
def with_ansi(*colors)
|
104
|
+
if @colorize
|
105
|
+
ANSI::Code.ansi(yield.to_s, *colors)
|
106
|
+
else
|
107
|
+
yield
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def ensure_space
|
112
|
+
append " " if @need_space
|
113
|
+
|
114
|
+
yield
|
115
|
+
|
116
|
+
@need_space = true
|
117
|
+
|
118
|
+
self
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|