ruby-libjit 0.1.0

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.
@@ -0,0 +1,52 @@
1
+ #ifndef minimal_node_h
2
+ #define minimal_node_h
3
+
4
+ #ifdef NEED_MINIMAL_NODE
5
+
6
+ #include "ruby.h"
7
+
8
+ typedef struct RNode {
9
+ unsigned long flags;
10
+ void * reserved;
11
+ union {
12
+ struct RNode * node;
13
+ VALUE (*cfunc)(ANYARGS);
14
+ } u1;
15
+ union {
16
+ struct RNode * node;
17
+ VALUE value;
18
+ } u2;
19
+ union {
20
+ struct RNode * node;
21
+ } u3;
22
+ } NODE;
23
+
24
+ #define nd_cfnc u1.cfunc
25
+ #define nd_rval u2.value
26
+
27
+ #define NEW_NODE(t,a0,a1,a2) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
28
+
29
+ /* TODO: No way to know the correct size of node_type */
30
+ enum node_type {
31
+ NODE_FOO,
32
+ };
33
+
34
+ void rb_add_method(VALUE, ID, NODE *, int);
35
+ NODE *rb_node_newnode(enum node_type, VALUE, VALUE, VALUE);
36
+
37
+ extern int NODE_MEMO;
38
+ extern int NODE_METHOD;
39
+ extern int NODE_FBODY;
40
+ extern int NODE_CFUNC;
41
+
42
+ void Init_minimal_node();
43
+
44
+ #define NOEX_PUBLIC 0x0
45
+
46
+ #define NEW_METHOD(n,x,v) NEW_NODE(NODE_METHOD,x,n,v)
47
+ #define NEW_FBODY(n,i) NEW_NODE(NODE_FBODY,i,n,0)
48
+ #define NEW_CFUNC(f,c) NEW_NODE(NODE_CFUNC,f,c,0)
49
+
50
+ #endif
51
+
52
+ #endif
data/ext/rubyjit.h ADDED
@@ -0,0 +1,20 @@
1
+ #ifndef RUBYJIT_H
2
+ #define RUBYJIT_H
3
+
4
+ enum Ruby_Libjit_Tag
5
+ {
6
+ RJT_OBJECT,
7
+ RJT_ID,
8
+ RJT_FUNCTION_PTR,
9
+ RJT_RUBY_VARARG_SIGNATURE,
10
+ RJT_VALUE_OBJECTS,
11
+ RJT_FUNCTIONS,
12
+ RJT_CONTEXT,
13
+ RJT_TAG_FOR_SIGNATURE
14
+ };
15
+
16
+ extern jit_type_t jit_type_VALUE;
17
+ extern jit_type_t jit_type_ID;
18
+ extern jit_type_t jit_type_Function_Ptr;
19
+
20
+ #endif
data/ext/rubypp.rb ADDED
@@ -0,0 +1,97 @@
1
+ class Preprocessor
2
+ def initialize(input, output, filename)
3
+ @input = input
4
+ @output = output
5
+ @filename = filename
6
+ @linenum = 1
7
+ end
8
+
9
+ def getline
10
+ line = @input.gets
11
+ @linenum += 1 if not line.nil?
12
+ return line
13
+ end
14
+
15
+ def preprocess
16
+ success = false
17
+ begin
18
+ loop do
19
+ line = getline
20
+ break if line.nil?
21
+ case line
22
+ when /(.*[^\\]|^)\#\{(.*?)\}(.*)/
23
+ puts "#{$1}#{evaluate($2, @linenum)}#{$3}"
24
+ when /^\#ruby\s+<<(.*)/
25
+ marker = $1
26
+ str = ''
27
+ evalstart = @linenum
28
+ loop do
29
+ line = getline
30
+ if line.nil? then
31
+ raise "End of input without #{marker}"
32
+ end
33
+ break if line.chomp == marker
34
+ str << line
35
+ end
36
+ result = evaluate(str, evalstart)
37
+ puts result if not result.nil?
38
+ when /^\#ruby\s+(.*)/
39
+ str = line = $1
40
+ while line[-1] == ?\\
41
+ str.chop!
42
+ line = getline
43
+ break if line.nil?
44
+ line.chomp!
45
+ str << line
46
+ end
47
+ result = evaluate(str, @linenum)
48
+ puts result if not result.nil?
49
+ else
50
+ puts line
51
+ end
52
+ end
53
+ success = true
54
+ ensure
55
+ if not success then
56
+ $stderr.puts "Error on line #{@linenum}:"
57
+ end
58
+ end
59
+ end
60
+
61
+ def evaluate(str, linenum)
62
+ result = eval(str, TOPLEVEL_BINDING, @filename, linenum)
63
+ success = true
64
+ return result
65
+ end
66
+
67
+ def puts(line='')
68
+ @output.puts(line)
69
+ end
70
+ end
71
+
72
+ def puts(line='')
73
+ $preprocessor.puts(line)
74
+ end
75
+
76
+ def rubypp(input_file, output_file)
77
+ input = input_file ? File.open(input_file) : $stdin
78
+ output = output_file ? File.open(output_file, 'w') : $stdout
79
+
80
+ success = false
81
+ begin
82
+ $preprocessor = Preprocessor.new(input, output, input_file || "(stdin)")
83
+ $preprocessor.preprocess()
84
+ success = true
85
+ ensure
86
+ if not success then
87
+ File.unlink(output_file) rescue Errno::ENOENT
88
+ end
89
+ end
90
+ end
91
+
92
+ if __FILE__ == $0 then
93
+ input_file = ARGV[0]
94
+ output_file = ARGV[1]
95
+ rubypp(input_file, output_file)
96
+ end
97
+
data/lib/jit/array.rb ADDED
@@ -0,0 +1,135 @@
1
+ require 'jit'
2
+ require 'jit/value'
3
+
4
+ module JIT
5
+
6
+ # An abstraction for a fixed-length array type.
7
+ #
8
+ # Example usage:
9
+ #
10
+ # array_type = JIT::Array.new(JIT::Type::INT, 4)
11
+ #
12
+ # JIT::Context.build do |context|
13
+ # signature = JIT::Type.create_signature(
14
+ # JIT::ABI::CDECL, JIT::Type::INT, [ ])
15
+ #
16
+ # function = JIT::Function.compile(context, signature) do |f|
17
+ # array_instance = array_type.create(f)
18
+ # array_instance[0] = f.const(JIT::Type::INT, 42)
19
+ # f.insn_return(array_instance[0])
20
+ # end
21
+ #
22
+ # end
23
+ #
24
+ class Array < JIT::Type
25
+ attr_reader :type
26
+ attr_reader :length
27
+
28
+ # Create a new JIT array type.
29
+ #
30
+ # +type+:: The type of the elements in the array.
31
+ # +length+:: The number of elements in the array.
32
+ #
33
+ def self.new(type, length)
34
+ array = self.create_struct([ type ] * length)
35
+ array.instance_eval do
36
+ @type = type
37
+ @length = length
38
+ end
39
+ return array
40
+ end
41
+
42
+ # Wrap an existing array.
43
+ #
44
+ # +ptr+:: A pointer to the first element in the array.
45
+ #
46
+ def wrap(ptr)
47
+ return Instance.wrap(self, ptr)
48
+ end
49
+
50
+ # Create a new array.
51
+ #
52
+ # +function+:: The JIT::Function this array will be used in.
53
+ #
54
+ def create(function)
55
+ instance = function.value(self)
56
+ ptr = function.insn_address_of(instance)
57
+ return wrap(ptr)
58
+ end
59
+
60
+ # Return the offset (in bytes) of the element at the given +index+.
61
+ #
62
+ # +index+:: The index of the desired element.
63
+ #
64
+ def offset_of(index)
65
+ return self.get_offset(index)
66
+ end
67
+
68
+ # Return the type of the element at the given +index+.
69
+ #
70
+ # +index+:: The index of the desired element.
71
+ #
72
+ def type_of(index)
73
+ return @type
74
+ end
75
+
76
+ # An abstraction for an instance of a fixed-length array.
77
+ #
78
+ class Instance < JIT::Value
79
+ attr_reader :array_type
80
+ attr_reader :type
81
+ attr_reader :ptr
82
+
83
+ # TODO: This breaks code below?
84
+ # attr_reader :function
85
+
86
+ # Wrap an existing array.
87
+ #
88
+ # +array_type+:: The JIT::Array type to wrap.
89
+ # +ptr+:: A pointer to the first element in the array.
90
+ #
91
+ def self.wrap(array_type, ptr)
92
+ pointer_type = JIT::Type.create_pointer(array_type)
93
+ value = self.new_value(ptr.function, pointer_type)
94
+ value.store(ptr)
95
+ value.instance_eval do
96
+ @array_type = array_type
97
+ @type = array_type.type
98
+ @function = ptr.function
99
+ @ptr = ptr
100
+ end
101
+ return value
102
+ end
103
+
104
+ # Generate JIT code to retrieve the element at the given +index+.
105
+ #
106
+ # +index+:: The index of the desired element. The value of the
107
+ # index must be known at compile-time.
108
+ #
109
+ def [](index)
110
+ @function.insn_load_relative(
111
+ @ptr,
112
+ @array_type.offset_of(index),
113
+ @array_type.type_of(index))
114
+ end
115
+
116
+ # Generate JIT code to assign to the element at the given +index+.
117
+ #
118
+ # +index+:: The index of the desired element. The value of the
119
+ # index must be known at compile-time.
120
+ # +value+:: The JIT::Value to assign to the element.
121
+ #
122
+ def []=(index, value)
123
+ @function.insn_store_relative(
124
+ @ptr,
125
+ @array_type.offset_of(index),
126
+ value)
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ if __FILE__ == $0 then
133
+ a = JIT::Array.new()
134
+ end
135
+
@@ -0,0 +1,201 @@
1
+ require 'jit'
2
+
3
+ module JIT
4
+ class Function
5
+ # An abstraction for conditionals.
6
+ #
7
+ # Example usage:
8
+ #
9
+ # function.if(condition) {
10
+ # # condition is true
11
+ # } .elsif(condition2) {
12
+ # # condition2 is true
13
+ # } .else {
14
+ # # condition1 and condition2 are false
15
+ # } .end
16
+ #
17
+ # Caution: if you omit end, then the generated code will have
18
+ # undefined behavior, but there will be no warning generated.
19
+ def if(cond, end_label = Label.new, &block)
20
+ false_label = Label.new
21
+ insn_branch_if_not(cond, false_label)
22
+ block.call
23
+ insn_branch(end_label)
24
+ insn_label(false_label)
25
+ return If.new(self, end_label)
26
+ end
27
+
28
+ # An abstraction for an inverted conditional.
29
+ #
30
+ # Example usage:
31
+ #
32
+ # function.unless(condition) {
33
+ # # condition is false
34
+ # } .elsunless(condition2) {
35
+ # # condition2 is false
36
+ # } .else {
37
+ # # condition1 and condition2 are true
38
+ # } .end
39
+ #
40
+ # Caution: if you omit end, then the generated code will have
41
+ # undefined behavior, but there will be no warning generated.
42
+ def unless(cond, end_label = Label.new, &block)
43
+ true_label = Label.new
44
+ insn_branch_if(cond, true_label)
45
+ block.call
46
+ insn_branch(end_label)
47
+ insn_label(true_label)
48
+ return If.new(self, end_label)
49
+ end
50
+
51
+ # :nodoc:
52
+ class If
53
+ def initialize(function, end_label)
54
+ @function = function
55
+ @end_label = end_label
56
+ end
57
+
58
+ def else(&block)
59
+ block.call
60
+ return self
61
+ end
62
+
63
+ def elsif(cond, &block)
64
+ return @function.if(cond, @end_label, &block)
65
+ end
66
+
67
+ def elsunless(cond, &block)
68
+ return @function.unless(cond, @end_label, &block)
69
+ end
70
+
71
+ def end
72
+ @function.insn_label(@end_label)
73
+ end
74
+ end
75
+
76
+ # An abstraction for a multi-way conditional.
77
+ #
78
+ # Example usage:
79
+ #
80
+ # function.case(value1)
81
+ # .when(value2) {
82
+ # # value1 == value2
83
+ # }.when(value3) {
84
+ # # value1 == value3
85
+ # } .else {
86
+ # # all other cases fell through
87
+ # } .end
88
+ #
89
+ # Caution: if you omit end, then the generated code will have
90
+ # undefined behavior, but there will be no warning generated.
91
+ def case(value)
92
+ return Case.new(self, value)
93
+ end
94
+
95
+ # :nodoc:
96
+ class Case
97
+ def initialize(function, value)
98
+ @function = function
99
+ @value = value
100
+ @if = nil
101
+ end
102
+
103
+ def when(value, &block)
104
+ if not @if then
105
+ @if = @function.if(value == @value, &block)
106
+ else
107
+ @if.elsif(value == @value, &block)
108
+ end
109
+ return self
110
+ end
111
+
112
+ def else(&block)
113
+ @if.else(&block)
114
+ end
115
+
116
+ def end
117
+ @if.end if @if
118
+ end
119
+ end
120
+
121
+ # Usage:
122
+ #
123
+ # until(proc { <condition> }) {
124
+ # # loop body
125
+ # } .end
126
+ #
127
+ def until(cond, &block)
128
+ start_label = Label.new
129
+ done_label = Label.new
130
+ insn_label(start_label)
131
+ insn_branch_if(cond.call, done_label)
132
+ loop = Loop.new(self, start_label, done_label)
133
+ block.call(loop)
134
+ insn_branch(start_label)
135
+ insn_label(done_label)
136
+ return loop
137
+ end
138
+
139
+ # Usage:
140
+ #
141
+ # while(proc { <condition> }) {
142
+ # # loop body
143
+ # } .end
144
+ #
145
+ def while(cond, &block)
146
+ start_label = Label.new
147
+ done_label = Label.new
148
+ insn_label(start_label)
149
+ insn_branch_if_not(cond.call, done_label)
150
+ loop = Loop.new(self, start_label, done_label)
151
+ block.call(loop)
152
+ insn_branch(start_label)
153
+ insn_label(done_label)
154
+ return loop
155
+ end
156
+
157
+ # :nodoc:
158
+ class Loop
159
+ def initialize(function, start_label, done_label)
160
+ @function = function
161
+ @redo_label = start_label
162
+ @done_label = done_label
163
+ end
164
+
165
+ def end
166
+ end
167
+
168
+ def break
169
+ @function.insn_branch(@done_label)
170
+ end
171
+
172
+ def redo
173
+ @function.insn_branch(@redo_label)
174
+ end
175
+
176
+ def redo_from_here
177
+ @redo_label = JIT::Label.new
178
+ @function.insn_label(@redo_label)
179
+ end
180
+ end
181
+
182
+ # An alias for get_param
183
+ def param(n)
184
+ self.get_param(n)
185
+ end
186
+
187
+ # An alias for insn_return
188
+ def return(result)
189
+ self.insn_return(result)
190
+ end
191
+
192
+ # Create a JIT::Context and compile a new function within that
193
+ # context.
194
+ def self.build(*args, &block)
195
+ JIT::Context.build do |context|
196
+ JIT::Function.compile(context, *args, &block)
197
+ end
198
+ end
199
+ end
200
+ end
201
+
data/lib/jit/struct.rb ADDED
@@ -0,0 +1,163 @@
1
+ require 'jit'
2
+
3
+ module JIT
4
+
5
+ # An abstraction for a record composed of heterogenous fields.
6
+ #
7
+ # Example usage:
8
+ #
9
+ # point_type = JIT::Struct.new(
10
+ # [ :x, JIT::Type::INT ],
11
+ # [ :y, JIT::Type::INT ],
12
+ # [ :z, JIT::Type::INT ])
13
+ #
14
+ # JIT::Context.build do |context|
15
+ # signature = JIT::Type.create_signature(
16
+ # JIT::ABI::CDECL, JIT::Type::INT, [ ])
17
+ #
18
+ # function = JIT::Function.compile(context, signature) do |f|
19
+ # point = point_type.create(f)
20
+ # point.x = function.const(JIT::Type::INT, 1)
21
+ # point.y = function.const(JIT::Type::INT, 2)
22
+ # point.z = function.const(JIT::Type::INT, 3)
23
+ # f.insn_return(point.x)
24
+ # end
25
+ #
26
+ # end
27
+ #
28
+ class Struct < JIT::Type
29
+
30
+ # Construct a new JIT structure type.
31
+ #
32
+ # +members+:: A list of members, where each element in the list is a
33
+ # two-element array [ :name, type ]
34
+ #
35
+ def self.new(*members)
36
+ member_names = members.map { |m| m[0].to_s.intern }
37
+ member_types = members.map { |m| m[1] }
38
+ type = self.create_struct(member_types)
39
+ type.instance_eval do
40
+ @members = members
41
+ @member_names = member_names
42
+ @member_types = member_types
43
+ @index = Hash[*@member_names.zip((0..@member_names.size).to_a).flatten]
44
+ end
45
+ return type
46
+ end
47
+
48
+ # Return the names of the members in the structure.
49
+ def members
50
+ return @member_names
51
+ end
52
+
53
+ # Wrap an existing structure.
54
+ #
55
+ # +ptr+:: A pointer to the first element in the structure.
56
+ #
57
+ def wrap(ptr)
58
+ return Instance.new(self, ptr)
59
+ end
60
+
61
+ # Create a new structure.
62
+ #
63
+ # +function+:: The JIT::Function this structure will be used in.
64
+ #
65
+ def create(function)
66
+ instance = function.value(self)
67
+ ptr = function.insn_address_of(instance)
68
+ return wrap(ptr)
69
+ end
70
+
71
+ # Return the offset (in bytes) of the element with the given name.
72
+ #
73
+ # +name+:: The name of the desired element.
74
+ #
75
+ def offset_of(name)
76
+ name = (Symbol === name) ? name : name.to_s.intern
77
+ return self.get_offset(@index[name])
78
+ end
79
+
80
+ # Change the offset of the element with the given name.
81
+ #
82
+ # +name+:: The name of the desired element.
83
+ # +offset+:: The new offset.
84
+ #
85
+ def set_offset_of(name, offset)
86
+ name = (Symbol === name) ? name : name.to_s.intern
87
+ return self.set_offset(@index[name], offset)
88
+ end
89
+
90
+ # Return the type of the element with the given name.
91
+ #
92
+ # +name+:: The name of the desired element.
93
+ #
94
+ def type_of(name)
95
+ name = (Symbol === name) ? name : name.to_s.intern
96
+ return @member_types[@index[name]]
97
+ end
98
+
99
+ # An abstraction for an instance of a JIT::Struct.
100
+ #
101
+ class Instance
102
+ attr_reader :ptr
103
+
104
+ # Wrap an existing structure.
105
+ #
106
+ # +struct+:: The JIT::Struct type to wrap.
107
+ # +ptr+ A pointer to the first element of the structure.
108
+ #
109
+ def initialize(struct, ptr)
110
+ @struct = struct
111
+ @function = ptr.function
112
+ @ptr = ptr
113
+
114
+ mod = Module.new do
115
+ struct.members.each do |name|
116
+ define_method("#{name}") do
117
+ self[name] # return
118
+ end
119
+
120
+ define_method("#{name}=") do |value|
121
+ self[name] = value # return
122
+ end
123
+ end
124
+ end
125
+
126
+ extend(mod)
127
+ end
128
+
129
+ # Generate JIT code to retrieve the element with the given name.
130
+ #
131
+ # +name+:: The name of the desired element.
132
+ #
133
+ def [](name)
134
+ @function.insn_load_relative(
135
+ @ptr,
136
+ @struct.offset_of(name),
137
+ @struct.type_of(name))
138
+ end
139
+
140
+ # Generate JIT code to assign to the element with the given name.
141
+ #
142
+ # +name+:: The name of the desired element.
143
+ # +value+:: The JIT::Value to assign to the element.
144
+ #
145
+ def []=(name, value)
146
+ @function.insn_store_relative(
147
+ @ptr,
148
+ @struct.offset_of(name),
149
+ value)
150
+ end
151
+
152
+ def members
153
+ return @struct.members
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ if __FILE__ == $0 then
160
+ s = JIT::Struct.new()
161
+ p s
162
+ end
163
+