This repository has been archived by the owner on Nov 2, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
builder.rb
108 lines (83 loc) · 2.17 KB
/
builder.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
module Furnace
class SSA::Builder
attr_reader :function
attr_accessor :block
def self.scope
SSA
end
def initialize(name, arguments=[], return_type=nil, options={})
if options[:instrument]
instrumentation = SSA::EventStream.new
end
@function = SSA::Function.new(name, [], return_type, instrumentation)
@function.arguments = arguments.map do |(type, name)|
SSA::Argument.new(type, name)
end
@block = @function.entry = add_block
end
def lookup_insn(opcode)
self.class.scope.const_get SSA.opcode_to_class_name(opcode)
end
def add_block
block = SSA::BasicBlock.new
@function.add block
if block_given?
branch block
@block = block
yield
else
block
end
end
def append(instruction, *args)
insn = lookup_insn(instruction).new(*args)
@block.append insn
insn
end
def branch(target)
append(:branch, [ target ])
end
def phi(type, mapping)
append(:phi, type, Hash[mapping])
end
def fork(post_block)
old_block = @block
new_block = add_block
@block = new_block
value = yield old_block
branch post_block
[ new_block, value ]
ensure
@block = old_block
end
def control_flow_op(instruction, type=Type::Variable.new, uses)
cond_block = @block
post_block = add_block
mapping = yield cond_block, post_block
targets = mapping.map { |(target, _)| target }
append(instruction, uses + targets)
@block = post_block
phi(type, mapping.map do |(target, value)|
if target == post_block
[cond_block, value]
else
[target, value]
end
end)
end
def return
append(:return)
end
def return_value(value)
append(:return_value, [ value ])
end
def method_missing(opcode, *args)
class_name = SSA.opcode_to_class_name(opcode)
if self.class.scope.const_defined? class_name
append opcode, *args
else
super
end
end
end
end