rubinius-compiler 1.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/rubinius/compiler.rb +11 -0
- data/lib/rubinius/compiler/compiled_file.rb +338 -0
- data/lib/rubinius/compiler/compiler.rb +377 -0
- data/lib/rubinius/compiler/evaluator.rb +334 -0
- data/lib/rubinius/compiler/generator.rb +646 -0
- data/lib/rubinius/compiler/generator_methods.rb +802 -0
- data/lib/rubinius/compiler/iseq.rb +146 -0
- data/lib/rubinius/compiler/locals.rb +147 -0
- data/lib/rubinius/compiler/opcodes.rb +150 -0
- data/lib/rubinius/compiler/printers.rb +115 -0
- data/lib/rubinius/compiler/runtime.rb +72 -0
- data/lib/rubinius/compiler/stages.rb +254 -0
- data/lib/rubinius/compiler/version.rb +5 -0
- data/rubinius-compiler.gemspec +22 -0
- metadata +91 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
# -*- encoding: us-ascii -*-
|
2
|
+
|
3
|
+
##
|
4
|
+
# Defines all the bytecode instructions used by the VM.
|
5
|
+
|
6
|
+
module Rubinius
|
7
|
+
class InstructionSet
|
8
|
+
|
9
|
+
class OpCode
|
10
|
+
attr_reader :args, :arg_count, :bytecode, :opcode, :size,
|
11
|
+
:stack, :stack_consumed, :stack_produced, :variable_stack,
|
12
|
+
:position, :produced_position, :stack_difference, :control_flow
|
13
|
+
|
14
|
+
alias_method :name, :opcode
|
15
|
+
alias_method :width, :size
|
16
|
+
|
17
|
+
def initialize(opcode, bytecode, params)
|
18
|
+
@opcode = opcode
|
19
|
+
@bytecode = bytecode
|
20
|
+
@args = params[:args]
|
21
|
+
@arg_count = @args.size
|
22
|
+
@size = @arg_count + 1
|
23
|
+
@position = nil
|
24
|
+
@produced_position = nil
|
25
|
+
|
26
|
+
@stack_consumed, @stack_produced = params[:stack]
|
27
|
+
if @stack_consumed.kind_of? Fixnum
|
28
|
+
if @stack_produced.kind_of? Fixnum
|
29
|
+
@variable_stack = false
|
30
|
+
@stack_difference = @stack_produced - @stack_consumed
|
31
|
+
else
|
32
|
+
@variable_stack = true
|
33
|
+
produced_extra, @produced_position, @produced_times = @stack_produced
|
34
|
+
@stack_difference = produced_extra - @stack_consumed
|
35
|
+
end
|
36
|
+
else
|
37
|
+
@variable_stack = true
|
38
|
+
extra, @position = @stack_consumed
|
39
|
+
|
40
|
+
if @stack_produced.kind_of? Fixnum
|
41
|
+
@stack_difference = @stack_produced - extra
|
42
|
+
else
|
43
|
+
produced_extra, @produced_position, @produced_times = @stack_produced
|
44
|
+
@stack_difference = produced_extra - extra
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
@control_flow = params[:control_flow]
|
49
|
+
end
|
50
|
+
|
51
|
+
def variable_stack?
|
52
|
+
@variable_stack
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
@opcode.to_s
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# InstructionSet methods
|
62
|
+
|
63
|
+
# Returns the opcode map.
|
64
|
+
def self.opcodes_map
|
65
|
+
@opcodes_map ||= Rubinius::LookupTable.new
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns an array of OpCode instances.
|
69
|
+
def self.opcodes
|
70
|
+
@opcodes ||= []
|
71
|
+
end
|
72
|
+
|
73
|
+
# Utility method for defining the opcodes.
|
74
|
+
def self.opcode(id, name, params={})
|
75
|
+
opcodes[id] = OpCode.new name, id, params
|
76
|
+
opcodes_map[name] = opcodes_map[id] = id
|
77
|
+
end
|
78
|
+
|
79
|
+
class InvalidOpCode < RuntimeError
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns an opcode given its name or numeric ID.
|
83
|
+
def self.[](name_or_id)
|
84
|
+
opcode = opcodes[opcodes_map[name_or_id]]
|
85
|
+
raise InvalidOpCode, "Invalid opcode #{op.inspect}" unless opcode
|
86
|
+
opcode
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Aids in decoding an instruction sequence into information
|
92
|
+
# about each instruction
|
93
|
+
#
|
94
|
+
class InstructionDecoder
|
95
|
+
def initialize(iseq)
|
96
|
+
@iseq = iseq
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Decodes an InstructionSequence (which is essentially a an array of ints)
|
101
|
+
# into an array whose elements are arrays of opcode symbols and 0-2 args,
|
102
|
+
# depending on the opcode.
|
103
|
+
|
104
|
+
def decode(symbols=false)
|
105
|
+
stream = decode_between(0, @iseq.size)
|
106
|
+
|
107
|
+
if symbols
|
108
|
+
stream.each { |i| i[0] = i[0].opcode }
|
109
|
+
end
|
110
|
+
|
111
|
+
return stream
|
112
|
+
end
|
113
|
+
|
114
|
+
def decode_between(start, fin)
|
115
|
+
offset = start
|
116
|
+
|
117
|
+
stream = []
|
118
|
+
|
119
|
+
while offset < fin
|
120
|
+
inst = @iseq[offset]
|
121
|
+
op = InstructionSet[inst]
|
122
|
+
|
123
|
+
case op.arg_count
|
124
|
+
when 0
|
125
|
+
stream << [op]
|
126
|
+
when 1
|
127
|
+
stream << [op, @iseq[offset+1]]
|
128
|
+
when 2
|
129
|
+
stream << [op, @iseq[offset+1], @iseq[offset+2]]
|
130
|
+
end
|
131
|
+
|
132
|
+
offset += op.width
|
133
|
+
end
|
134
|
+
|
135
|
+
return stream
|
136
|
+
end
|
137
|
+
|
138
|
+
def show
|
139
|
+
ip = 0
|
140
|
+
decode.each do |inst|
|
141
|
+
puts "%4s: %s" % [ip, inst.join(" ")]
|
142
|
+
ip += inst.size
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# -*- encoding: us-ascii -*-
|
2
|
+
|
3
|
+
module Rubinius::ToolSet.current::TS
|
4
|
+
class Compiler
|
5
|
+
module LocalVariables
|
6
|
+
def variables
|
7
|
+
@variables ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def local_count
|
11
|
+
variables.size
|
12
|
+
end
|
13
|
+
|
14
|
+
def local_names
|
15
|
+
names = []
|
16
|
+
eval_names = []
|
17
|
+
variables.each_pair do |name, var|
|
18
|
+
case var
|
19
|
+
when EvalLocalVariable
|
20
|
+
eval_names << name
|
21
|
+
when LocalVariable
|
22
|
+
names[var.slot] = name
|
23
|
+
# We ignore NestedLocalVariables because they're
|
24
|
+
# tagged as existing only in their source scope.
|
25
|
+
end
|
26
|
+
end
|
27
|
+
names += eval_names
|
28
|
+
end
|
29
|
+
|
30
|
+
def allocate_slot
|
31
|
+
variables.size
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class LocalVariable
|
36
|
+
attr_reader :slot
|
37
|
+
|
38
|
+
def initialize(slot)
|
39
|
+
@slot = slot
|
40
|
+
end
|
41
|
+
|
42
|
+
def reference
|
43
|
+
LocalReference.new @slot
|
44
|
+
end
|
45
|
+
|
46
|
+
def nested_reference
|
47
|
+
NestedLocalReference.new @slot
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class NestedLocalVariable
|
52
|
+
attr_reader :depth, :slot
|
53
|
+
|
54
|
+
def initialize(depth, slot)
|
55
|
+
@depth = depth
|
56
|
+
@slot = slot
|
57
|
+
end
|
58
|
+
|
59
|
+
def reference
|
60
|
+
NestedLocalReference.new @slot, @depth
|
61
|
+
end
|
62
|
+
|
63
|
+
alias_method :nested_reference, :reference
|
64
|
+
end
|
65
|
+
|
66
|
+
class EvalLocalVariable
|
67
|
+
attr_reader :name
|
68
|
+
|
69
|
+
def initialize(name)
|
70
|
+
@name = name
|
71
|
+
end
|
72
|
+
|
73
|
+
def reference
|
74
|
+
EvalLocalReference.new @name
|
75
|
+
end
|
76
|
+
|
77
|
+
alias_method :nested_reference, :reference
|
78
|
+
end
|
79
|
+
|
80
|
+
class LocalReference
|
81
|
+
attr_reader :slot
|
82
|
+
|
83
|
+
def initialize(slot)
|
84
|
+
@slot = slot
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_bytecode(g)
|
88
|
+
g.push_local @slot
|
89
|
+
end
|
90
|
+
|
91
|
+
def set_bytecode(g)
|
92
|
+
g.set_local @slot
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class NestedLocalReference
|
97
|
+
attr_accessor :depth
|
98
|
+
attr_reader :slot
|
99
|
+
|
100
|
+
def initialize(slot, depth=0)
|
101
|
+
@slot = slot
|
102
|
+
@depth = depth
|
103
|
+
end
|
104
|
+
|
105
|
+
def get_bytecode(g)
|
106
|
+
if @depth == 0
|
107
|
+
g.push_local @slot
|
108
|
+
else
|
109
|
+
g.push_local_depth @depth, @slot
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def set_bytecode(g)
|
114
|
+
if @depth == 0
|
115
|
+
g.set_local @slot
|
116
|
+
else
|
117
|
+
g.set_local_depth @depth, @slot
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class EvalLocalReference
|
123
|
+
|
124
|
+
# Ignored, but simplifies duck-typing references
|
125
|
+
attr_accessor :depth
|
126
|
+
|
127
|
+
def initialize(name)
|
128
|
+
@name = name
|
129
|
+
@depth = 0
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_bytecode(g)
|
133
|
+
g.push_variables
|
134
|
+
g.push_literal @name
|
135
|
+
g.send :get_eval_local, 1, false
|
136
|
+
end
|
137
|
+
|
138
|
+
def set_bytecode(g)
|
139
|
+
g.push_variables
|
140
|
+
g.swap
|
141
|
+
g.push_literal @name
|
142
|
+
g.swap
|
143
|
+
g.send :set_eval_local, 2, false
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# *** This file is generated by InstructionParser ***
|
2
|
+
|
3
|
+
module Rubinius
|
4
|
+
class InstructionSet
|
5
|
+
opcode 0, :noop, :stack => [0, 0], :args => [], :control_flow => :next
|
6
|
+
|
7
|
+
# Push primitive values
|
8
|
+
opcode 1, :push_nil, :stack => [0, 1], :args => [], :control_flow => :next
|
9
|
+
opcode 2, :push_true, :stack => [0, 1], :args => [], :control_flow => :next
|
10
|
+
opcode 3, :push_false, :stack => [0, 1], :args => [], :control_flow => :next
|
11
|
+
opcode 4, :push_int, :stack => [0, 1], :args => [:number], :control_flow => :next
|
12
|
+
opcode 5, :push_self, :stack => [0, 1], :args => [], :control_flow => :next
|
13
|
+
|
14
|
+
# Manipulate literals
|
15
|
+
opcode 6, :set_literal, :stack => [1, 1], :args => [:literal], :control_flow => :next
|
16
|
+
opcode 7, :push_literal, :stack => [0, 1], :args => [:literal], :control_flow => :next
|
17
|
+
|
18
|
+
# Flow control
|
19
|
+
opcode 8, :goto, :stack => [0, 0], :args => [:location], :control_flow => :branch
|
20
|
+
opcode 9, :goto_if_false, :stack => [1, 0], :args => [:location], :control_flow => :branch
|
21
|
+
opcode 10, :goto_if_true, :stack => [1, 0], :args => [:location], :control_flow => :branch
|
22
|
+
opcode 11, :ret, :stack => [1, 1], :args => [], :control_flow => :return
|
23
|
+
|
24
|
+
# Stack manipulations
|
25
|
+
opcode 12, :swap_stack, :stack => [2, 2], :args => [], :control_flow => :next
|
26
|
+
opcode 13, :dup_top, :stack => [1, 2], :args => [], :control_flow => :next
|
27
|
+
opcode 14, :dup_many, :stack => [[0,1], [0, 1, 2]],:args => [:count], :control_flow => :next
|
28
|
+
opcode 15, :pop, :stack => [1, 0], :args => [], :control_flow => :next
|
29
|
+
opcode 16, :pop_many, :stack => [[0,1], 0], :args => [:count], :control_flow => :next
|
30
|
+
opcode 17, :rotate, :stack => [[0,1], [0, 1, 1]],:args => [:count], :control_flow => :next
|
31
|
+
opcode 18, :move_down, :stack => [[0,1], [0, 1, 1]],:args => [:positions], :control_flow => :next
|
32
|
+
|
33
|
+
# Manipulate local variables
|
34
|
+
opcode 19, :set_local, :stack => [1, 1], :args => [:local], :control_flow => :next
|
35
|
+
opcode 20, :push_local, :stack => [0, 1], :args => [:local], :control_flow => :next
|
36
|
+
opcode 21, :push_local_depth, :stack => [0, 1], :args => [:depth, :index], :control_flow => :next
|
37
|
+
opcode 22, :set_local_depth, :stack => [1, 1], :args => [:depth, :index], :control_flow => :next
|
38
|
+
opcode 23, :passed_arg, :stack => [0, 1], :args => [:index], :control_flow => :next
|
39
|
+
|
40
|
+
# Manipulate exceptions
|
41
|
+
opcode 24, :push_current_exception, :stack => [0, 1], :args => [], :control_flow => :next
|
42
|
+
opcode 25, :clear_exception, :stack => [0, 0], :args => [], :control_flow => :next
|
43
|
+
opcode 26, :push_exception_state, :stack => [0, 1], :args => [], :control_flow => :next
|
44
|
+
opcode 27, :restore_exception_state, :stack => [1, 0], :args => [], :control_flow => :next
|
45
|
+
opcode 28, :raise_exc, :stack => [1, 0], :args => [], :control_flow => :raise
|
46
|
+
opcode 29, :setup_unwind, :stack => [0, 0], :args => [:ip, :type], :control_flow => :handler
|
47
|
+
opcode 30, :pop_unwind, :stack => [0, 0], :args => [], :control_flow => :next
|
48
|
+
opcode 31, :raise_return, :stack => [1, 1], :args => [], :control_flow => :raise
|
49
|
+
opcode 32, :ensure_return, :stack => [1, 1], :args => [], :control_flow => :raise
|
50
|
+
opcode 33, :raise_break, :stack => [1, 1], :args => [], :control_flow => :raise
|
51
|
+
opcode 34, :reraise, :stack => [0, 0], :args => [], :control_flow => :raise
|
52
|
+
|
53
|
+
# Manipulate arrays
|
54
|
+
opcode 35, :make_array, :stack => [[0,1], 1], :args => [:count], :control_flow => :next
|
55
|
+
opcode 36, :cast_array, :stack => [1, 1], :args => [], :control_flow => :next
|
56
|
+
opcode 37, :shift_array, :stack => [1, 2], :args => [], :control_flow => :next
|
57
|
+
|
58
|
+
# Manipulate instance variables
|
59
|
+
opcode 38, :set_ivar, :stack => [1, 1], :args => [:literal], :control_flow => :next
|
60
|
+
opcode 39, :push_ivar, :stack => [0, 1], :args => [:literal], :control_flow => :next
|
61
|
+
|
62
|
+
# Manipulate constants
|
63
|
+
opcode 40, :push_const, :stack => [0, 1], :args => [:literal], :control_flow => :next
|
64
|
+
opcode 41, :set_const, :stack => [1, 1], :args => [:literal], :control_flow => :next
|
65
|
+
opcode 42, :set_const_at, :stack => [2, 1], :args => [:literal], :control_flow => :next
|
66
|
+
opcode 43, :find_const, :stack => [1, 1], :args => [:literal], :control_flow => :next
|
67
|
+
opcode 44, :push_cpath_top, :stack => [0, 1], :args => [], :control_flow => :next
|
68
|
+
opcode 45, :push_const_fast, :stack => [0, 1], :args => [:literal], :control_flow => :next
|
69
|
+
opcode 46, :find_const_fast, :stack => [1, 1], :args => [:literal], :control_flow => :next
|
70
|
+
|
71
|
+
# Send messages
|
72
|
+
opcode 47, :set_call_flags, :stack => [0, 0], :args => [:flags], :control_flow => :next
|
73
|
+
opcode 48, :allow_private, :stack => [0, 0], :args => [], :control_flow => :next
|
74
|
+
opcode 49, :send_method, :stack => [1, 1], :args => [:literal], :control_flow => :send
|
75
|
+
opcode 50, :send_stack, :stack => [[1,2], 1], :args => [:literal, :count], :control_flow => :send
|
76
|
+
opcode 51, :send_stack_with_block, :stack => [[2,2], 1], :args => [:literal, :count], :control_flow => :send
|
77
|
+
|
78
|
+
CALL_FLAG_CONCAT = 2
|
79
|
+
|
80
|
+
opcode 52, :send_stack_with_splat, :stack => [[3,2], 1], :args => [:literal, :count], :control_flow => :send
|
81
|
+
opcode 53, :send_super_stack_with_block, :stack => [[1,2], 1], :args => [:literal, :count], :control_flow => :send
|
82
|
+
opcode 54, :send_super_stack_with_splat, :stack => [[2,2], 1], :args => [:literal, :count], :control_flow => :send
|
83
|
+
|
84
|
+
# Manipulate blocks
|
85
|
+
opcode 55, :push_block, :stack => [0, 1], :args => [], :control_flow => :next
|
86
|
+
opcode 56, :passed_blockarg, :stack => [0, 1], :args => [:count], :control_flow => :next
|
87
|
+
opcode 57, :create_block, :stack => [0, 1], :args => [:literal], :control_flow => :next
|
88
|
+
opcode 58, :cast_for_single_block_arg, :stack => [0, 1], :args => [], :control_flow => :next
|
89
|
+
opcode 59, :cast_for_multi_block_arg, :stack => [0, 1], :args => [], :control_flow => :next
|
90
|
+
opcode 60, :cast_for_splat_block_arg, :stack => [0, 1], :args => [], :control_flow => :next
|
91
|
+
opcode 61, :yield_stack, :stack => [[0,1], 1], :args => [:count], :control_flow => :yield
|
92
|
+
opcode 62, :yield_splat, :stack => [[1,1], 1], :args => [:count], :control_flow => :yield
|
93
|
+
|
94
|
+
# Manipulate strings
|
95
|
+
opcode 63, :string_append, :stack => [2, 1], :args => [], :control_flow => :next
|
96
|
+
opcode 64, :string_build, :stack => [[0,1], 1], :args => [:count], :control_flow => :next
|
97
|
+
opcode 65, :string_dup, :stack => [1, 1], :args => [], :control_flow => :next
|
98
|
+
|
99
|
+
# Manipulate scope
|
100
|
+
opcode 66, :push_scope, :stack => [0, 1], :args => [], :control_flow => :next
|
101
|
+
opcode 67, :add_scope, :stack => [1, 0], :args => [], :control_flow => :next
|
102
|
+
opcode 68, :push_variables, :stack => [0, 1], :args => [], :control_flow => :next
|
103
|
+
|
104
|
+
# Miscellaneous. TODO: better categorize these
|
105
|
+
opcode 69, :check_interrupts, :stack => [0, 0], :args => [], :control_flow => :next
|
106
|
+
opcode 70, :yield_debugger, :stack => [0, 0], :args => [], :control_flow => :next
|
107
|
+
opcode 71, :is_nil, :stack => [1, 1], :args => [], :control_flow => :next
|
108
|
+
opcode 72, :check_serial, :stack => [1, 1], :args => [:literal, :serial], :control_flow => :next
|
109
|
+
opcode 73, :check_serial_private, :stack => [1, 1], :args => [:literal, :serial], :control_flow => :next
|
110
|
+
|
111
|
+
# Access object fields
|
112
|
+
opcode 74, :push_my_field, :stack => [0, 1], :args => [:index], :control_flow => :next
|
113
|
+
opcode 75, :store_my_field, :stack => [1, 1], :args => [:index], :control_flow => :next
|
114
|
+
|
115
|
+
# Type checks
|
116
|
+
opcode 76, :kind_of, :stack => [2, 1], :args => [], :control_flow => :next
|
117
|
+
opcode 77, :instance_of, :stack => [2, 1], :args => [], :control_flow => :next
|
118
|
+
|
119
|
+
# Optimizations
|
120
|
+
opcode 78, :meta_push_neg_1, :stack => [0, 1], :args => [], :control_flow => :next
|
121
|
+
opcode 79, :meta_push_0, :stack => [0, 1], :args => [], :control_flow => :next
|
122
|
+
opcode 80, :meta_push_1, :stack => [0, 1], :args => [], :control_flow => :next
|
123
|
+
opcode 81, :meta_push_2, :stack => [0, 1], :args => [], :control_flow => :next
|
124
|
+
opcode 82, :meta_send_op_plus, :stack => [2, 1], :args => [:literal], :control_flow => :send
|
125
|
+
opcode 83, :meta_send_op_minus, :stack => [2, 1], :args => [:literal], :control_flow => :send
|
126
|
+
opcode 84, :meta_send_op_equal, :stack => [2, 1], :args => [:literal], :control_flow => :send
|
127
|
+
opcode 85, :meta_send_op_lt, :stack => [2, 1], :args => [:literal], :control_flow => :next
|
128
|
+
opcode 86, :meta_send_op_gt, :stack => [2, 1], :args => [:literal], :control_flow => :next
|
129
|
+
opcode 87, :meta_send_op_tequal, :stack => [2, 1], :args => [:literal], :control_flow => :send
|
130
|
+
opcode 88, :meta_send_call, :stack => [[1,2], 1], :args => [:literal, :count], :control_flow => :send
|
131
|
+
|
132
|
+
# More misc
|
133
|
+
opcode 89, :push_my_offset, :stack => [0, 1], :args => [:index], :control_flow => :next
|
134
|
+
opcode 90, :zsuper, :stack => [1, 1], :args => [:literal], :control_flow => :next
|
135
|
+
opcode 91, :push_block_arg, :stack => [0, 1], :args => [], :control_flow => :next
|
136
|
+
opcode 92, :push_undef, :stack => [0, 1], :args => [], :control_flow => :next
|
137
|
+
opcode 93, :push_stack_local, :stack => [0, 1], :args => [:which], :control_flow => :next
|
138
|
+
opcode 94, :set_stack_local, :stack => [1, 1], :args => [:which], :control_flow => :next
|
139
|
+
opcode 95, :push_has_block, :stack => [0, 1], :args => [], :control_flow => :next
|
140
|
+
opcode 96, :push_proc, :stack => [0, 1], :args => [], :control_flow => :next
|
141
|
+
opcode 97, :check_frozen, :stack => [1, 1], :args => [], :control_flow => :next
|
142
|
+
opcode 98, :cast_multi_value, :stack => [1, 1], :args => [], :control_flow => :next
|
143
|
+
opcode 99, :invoke_primitive, :stack => [[0,2], 1], :args => [:literal, :count], :control_flow => :next
|
144
|
+
opcode 100, :push_rubinius, :stack => [0, 1], :args => [], :control_flow => :next
|
145
|
+
opcode 101, :call_custom, :stack => [[1,2], 1], :args => [:literal, :count], :control_flow => :send
|
146
|
+
opcode 102, :meta_to_s, :stack => [1, 1], :args => [:literal], :control_flow => :send
|
147
|
+
opcode 103, :push_type, :stack => [0, 1], :args => [], :control_flow => :next
|
148
|
+
opcode 104, :push_mirror, :stack => [0, 1], :args => [], :control_flow => :next
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# -*- encoding: us-ascii -*-
|
2
|
+
|
3
|
+
module Rubinius::ToolSet.current::TS
|
4
|
+
class Compiler
|
5
|
+
class Printer < Stage
|
6
|
+
def initialize
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class ASTPrinter < Printer
|
11
|
+
def run
|
12
|
+
@input.ascii_graph
|
13
|
+
@output = @input
|
14
|
+
run_next
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class SexpPrinter < Printer
|
19
|
+
def run
|
20
|
+
require 'pp'
|
21
|
+
|
22
|
+
puts @input.to_sexp.pretty_inspect
|
23
|
+
@output = @input
|
24
|
+
run_next
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class MethodPrinter < Printer
|
29
|
+
attr_accessor :bytecode, :assembly
|
30
|
+
|
31
|
+
SEPARATOR_SIZE = 40
|
32
|
+
|
33
|
+
def method_names=(names)
|
34
|
+
return if names.empty?
|
35
|
+
@method_names = names.map { |n| n.to_sym }
|
36
|
+
end
|
37
|
+
|
38
|
+
def match?(name)
|
39
|
+
return true unless @method_names
|
40
|
+
@method_names.include? name
|
41
|
+
end
|
42
|
+
|
43
|
+
def print_header(code)
|
44
|
+
name = code.name.inspect
|
45
|
+
size = (SEPARATOR_SIZE - name.size - 2) / 2
|
46
|
+
size = 1 if size <= 0
|
47
|
+
puts "\n#{"=" * size} #{name} #{"=" * (size + name.size % 2)}"
|
48
|
+
print "Arguments: "
|
49
|
+
print "#{code.required_args} required, "
|
50
|
+
print "#{code.post_args} post, "
|
51
|
+
print "#{code.total_args} total"
|
52
|
+
print code.splat ? ", (splat #{code.splat})\n" : "\n"
|
53
|
+
puts "Arity: #{code.arity}"
|
54
|
+
print "Locals: #{code.local_count}"
|
55
|
+
print code.local_count > 0 ? ": #{code.local_names.join ", "}\n" : "\n"
|
56
|
+
puts "Stack size: #{code.stack_size}"
|
57
|
+
literals = code.literals.collect do |literal|
|
58
|
+
case literal
|
59
|
+
when CompiledCode
|
60
|
+
"<compiled code>"
|
61
|
+
else
|
62
|
+
literal.inspect
|
63
|
+
end
|
64
|
+
end
|
65
|
+
print "Literals: #{literals.size}"
|
66
|
+
print code.literals.size > 0 ? ": #{literals.join ", "}\n" : "\n"
|
67
|
+
print_lines code
|
68
|
+
puts
|
69
|
+
end
|
70
|
+
|
71
|
+
def print_footer
|
72
|
+
puts "-" * SEPARATOR_SIZE
|
73
|
+
end
|
74
|
+
|
75
|
+
def print_lines(code)
|
76
|
+
lines = code.lines
|
77
|
+
size = lines.size - 1
|
78
|
+
i = 1
|
79
|
+
|
80
|
+
if lines[0] == -1
|
81
|
+
puts "Line: #{lines[1]}"
|
82
|
+
i += 2
|
83
|
+
end
|
84
|
+
|
85
|
+
print "Lines to IP: "
|
86
|
+
while i < size
|
87
|
+
print "#{lines[i]}: #{lines[i - 1]}..#{lines[i + 1] - 1}"
|
88
|
+
i += 2
|
89
|
+
print ", " if i < size
|
90
|
+
end
|
91
|
+
puts
|
92
|
+
end
|
93
|
+
|
94
|
+
def print_method(code)
|
95
|
+
if match? code.name
|
96
|
+
print_header code
|
97
|
+
puts code.decode if @bytecode
|
98
|
+
print_footer
|
99
|
+
end
|
100
|
+
|
101
|
+
code.literals.each do |m|
|
102
|
+
next unless m.kind_of? Rubinius::CompiledCode
|
103
|
+
print_method m
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def run
|
108
|
+
print_method @input
|
109
|
+
|
110
|
+
@output = @input
|
111
|
+
run_next
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|