rubinius-compiler 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|