ikra 0.0.1 → 0.0.2

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.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ast/builder.rb +225 -77
  3. data/lib/ast/host_section_builder.rb +38 -0
  4. data/lib/ast/interpreter.rb +67 -0
  5. data/lib/ast/lexical_variables_enumerator.rb +3 -2
  6. data/lib/ast/nodes.rb +521 -31
  7. data/lib/ast/printer.rb +116 -18
  8. data/lib/ast/ssa_generator.rb +192 -0
  9. data/lib/ast/visitor.rb +235 -21
  10. data/lib/config/configuration.rb +28 -3
  11. data/lib/config/os_configuration.rb +62 -9
  12. data/lib/cpu/cpu_implementation.rb +39 -0
  13. data/lib/ikra.rb +13 -3
  14. data/lib/resources/cuda/allocate_device_memory.cpp +5 -0
  15. data/lib/resources/cuda/allocate_host_memory.cpp +1 -0
  16. data/lib/resources/cuda/allocate_memcpy_environment_to_device.cpp +11 -0
  17. data/lib/resources/cuda/ast/assignment.cpp +1 -0
  18. data/lib/resources/cuda/block_function_head.cpp +7 -1
  19. data/lib/resources/cuda/entry_point.cpp +47 -0
  20. data/lib/resources/cuda/env_builder_copy_array.cpp +8 -2
  21. data/lib/resources/cuda/free_device_memory.cpp +3 -0
  22. data/lib/resources/cuda/free_memory_for_command.cpp +24 -0
  23. data/lib/resources/cuda/header.cpp +23 -9
  24. data/lib/resources/cuda/header_structs.cpp +92 -0
  25. data/lib/resources/cuda/host_section_block_function_head.cpp +12 -0
  26. data/lib/resources/cuda/host_section_entry_point.cpp +55 -0
  27. data/lib/resources/cuda/host_section_free_device_memory.cpp +18 -0
  28. data/lib/resources/cuda/host_section_launch_parallel_section.cpp +14 -0
  29. data/lib/resources/cuda/host_section_malloc_memcpy_device_to_host.cpp +10 -0
  30. data/lib/resources/cuda/kernel.cpp +9 -2
  31. data/lib/resources/cuda/launch_kernel.cpp +5 -0
  32. data/lib/resources/cuda/memcpy_device_to_host.cpp +3 -0
  33. data/lib/resources/cuda/memcpy_device_to_host_expr.cpp +10 -0
  34. data/lib/resources/cuda/reduce_body.cpp +88 -0
  35. data/lib/resources/cuda/stencil_array_reconstruction.cpp +2 -0
  36. data/lib/resources/cuda/stencil_body.cpp +16 -0
  37. data/lib/resources/cuda/struct_definition.cpp +4 -0
  38. data/lib/ruby_core/array.rb +34 -0
  39. data/lib/ruby_core/array_command.rb +313 -0
  40. data/lib/ruby_core/core.rb +103 -0
  41. data/lib/ruby_core/interpreter.rb +16 -0
  42. data/lib/ruby_core/math.rb +32 -0
  43. data/lib/ruby_core/ruby_integration.rb +256 -0
  44. data/lib/symbolic/host_section.rb +115 -0
  45. data/lib/symbolic/input.rb +87 -0
  46. data/lib/symbolic/input_visitor.rb +68 -0
  47. data/lib/symbolic/symbolic.rb +793 -117
  48. data/lib/symbolic/visitor.rb +70 -8
  49. data/lib/translator/array_command_struct_builder.rb +163 -0
  50. data/lib/translator/ast_translator.rb +572 -0
  51. data/lib/translator/block_translator.rb +104 -48
  52. data/lib/translator/commands/array_combine_command.rb +41 -0
  53. data/lib/translator/commands/array_identity_command.rb +28 -0
  54. data/lib/translator/commands/array_index_command.rb +52 -0
  55. data/lib/translator/commands/array_reduce_command.rb +135 -0
  56. data/lib/translator/commands/array_stencil_command.rb +129 -0
  57. data/lib/translator/commands/array_zip_command.rb +30 -0
  58. data/lib/translator/commands/command_translator.rb +264 -0
  59. data/lib/translator/cuda_errors.rb +32 -0
  60. data/lib/translator/environment_builder.rb +263 -0
  61. data/lib/translator/host_section/array_host_section_command.rb +150 -0
  62. data/lib/translator/host_section/array_in_host_section_command.rb +41 -0
  63. data/lib/translator/host_section/ast_translator.rb +14 -0
  64. data/lib/translator/host_section/parallel_section_invocation_visitor.rb +20 -0
  65. data/lib/translator/host_section/program_builder.rb +89 -0
  66. data/lib/translator/input_translator.rb +226 -0
  67. data/lib/translator/kernel_builder.rb +137 -0
  68. data/lib/translator/kernel_launcher/for_loop_kernel_launcher.rb +40 -0
  69. data/lib/translator/kernel_launcher/kernel_launcher.rb +259 -0
  70. data/lib/translator/kernel_launcher/while_loop_kernel_launcher.rb +38 -0
  71. data/lib/translator/last_returns_visitor.rb +19 -10
  72. data/lib/translator/program_builder.rb +197 -0
  73. data/lib/translator/program_launcher.rb +273 -0
  74. data/lib/translator/struct_type.rb +55 -0
  75. data/lib/translator/translator.rb +34 -11
  76. data/lib/translator/variable_classifier_visitor.rb +56 -0
  77. data/lib/types/inference/ast_inference.rb +586 -0
  78. data/lib/types/inference/clear_types_visitor.rb +11 -0
  79. data/lib/types/inference/command_inference.rb +101 -0
  80. data/lib/types/inference/input_inference.rb +62 -0
  81. data/lib/types/{object_tracer.rb → inference/object_tracer.rb} +5 -6
  82. data/lib/types/inference/ruby_extension.rb +35 -0
  83. data/lib/types/inference/symbol_table.rb +131 -0
  84. data/lib/types/types.rb +14 -0
  85. data/lib/types/types/array_command_type.rb +123 -0
  86. data/lib/types/types/array_type.rb +137 -0
  87. data/lib/types/{class_type.rb → types/class_type.rb} +42 -18
  88. data/lib/types/{primitive_type.rb → types/primitive_type.rb} +20 -7
  89. data/lib/types/types/ruby_type.rb +88 -0
  90. data/lib/types/types/struct_type.rb +179 -0
  91. data/lib/types/types/union_type.rb +239 -0
  92. metadata +160 -18
  93. data/lib/ast/method_definition.rb +0 -37
  94. data/lib/ast/translator.rb +0 -264
  95. data/lib/resources/cuda/kernel_launcher.cpp +0 -28
  96. data/lib/scope.rb +0 -166
  97. data/lib/translator/command_translator.rb +0 -421
  98. data/lib/translator/local_variables_enumerator.rb +0 -35
  99. data/lib/translator/method_translator.rb +0 -24
  100. data/lib/types/array_type.rb +0 -51
  101. data/lib/types/ruby_extension.rb +0 -67
  102. data/lib/types/ruby_type.rb +0 -45
  103. data/lib/types/type_inference.rb +0 -382
  104. data/lib/types/union_type.rb +0 -155
@@ -1,37 +0,0 @@
1
- require "set"
2
- require_relative "../scope"
3
-
4
- module Ikra
5
- module AST
6
- class MethodDefinition
7
- attr_accessor :type # receiver type
8
- attr_accessor :selector
9
- attr_accessor :ast
10
- attr_accessor :return_type
11
- attr_accessor :callers # method definitions calling this method
12
- attr_accessor :symbol_table
13
- attr_accessor :binding # needed for resolving constants
14
- attr_accessor :local_variables # local variables defined in the method (name -> type)
15
- attr_accessor :lexical_variables # lexical variables (defined outside; name -> type)
16
- attr_accessor :accessed_lexical_variables # accessed lexical variables, only these variables are transferred to the GPU. TODO: Do we still need this? This is now determined in symbolic.rb
17
- attr_accessor :parameter_variables # parameters of the method/block (name -> type)
18
-
19
- def initialize(type:, selector:, parameter_variables:, return_type:, ast:)
20
- @type = type
21
- @selector = selector
22
- @parameter_variables = parameter_variables
23
- @return_type = return_type
24
- @ast = ast
25
- @callers = Set.new
26
- @symbol_table = Scope.new
27
- @local_variables = {}
28
- @lexical_variables = {} # optional
29
- @accessed_lexical_variables = {} # optional
30
- end
31
-
32
- def parameter_names
33
- type.method_parameters(selector)
34
- end
35
- end
36
- end
37
- end
@@ -1,264 +0,0 @@
1
- require_relative "nodes.rb"
2
- require_relative "../translator/translator"
3
-
4
- # Rule: every statement ends with newline
5
-
6
- module Ikra
7
- module AST
8
- class Node
9
- @@next_temp_identifier_id = 0
10
-
11
- def translate_statement
12
- translate_expression + ";\n"
13
- end
14
-
15
- protected
16
-
17
- def statements_as_expression(str)
18
- "[&]{ #{str} }()"
19
- end
20
-
21
- def indent_block(str)
22
- str.split("\n").map do |line| " " + line end.join("\n")
23
- end
24
-
25
- def wrap_in_c_block(str)
26
- "{\n" + indent_block(str) + "\n}\n"
27
- end
28
-
29
- def temp_identifier_id
30
- @@next_temp_identifier_id += 1
31
- @@next_temp_identifier_id
32
- end
33
-
34
- # Generates code that assigns the value of a node to a newly-defined variable.
35
- def define_assign_variable(name, node)
36
- type = node.get_type.to_c_type
37
- "#{type} #{name} = #{node.translate_expression};"
38
- end
39
- end
40
-
41
- class RootNode
42
- def translate_statement
43
- child.translate_statement
44
- end
45
-
46
- def translate_expression
47
- child.translate_expression
48
- end
49
- end
50
-
51
- class ConstNode
52
- def translate_expression
53
- raise "Not implemented"
54
- end
55
- end
56
-
57
- class LVarReadNode
58
- def translate_expression
59
- identifier.to_s
60
- end
61
- end
62
-
63
- class LVarWriteNode
64
- def translate_expression
65
- "#{identifier.to_s} = #{value.translate_expression}"
66
- end
67
- end
68
-
69
- class IVarReadNode
70
- def translate_expression
71
- array_identifier = class_owner.to_ikra_type.inst_var_array_name(identifier)
72
- "#{Translator::Constants::ENV_IDENTIFIER}->#{array_identifier}[#{Constants::SELF_IDENTIFIER}]"
73
- end
74
- end
75
-
76
- class IntNode
77
- def translate_expression
78
- value.to_s
79
- end
80
- end
81
-
82
- class FloatNode
83
- def translate_expression
84
- value.to_s
85
- end
86
- end
87
-
88
- class BoolNode
89
- def translate_expression
90
- value.to_s
91
- end
92
- end
93
-
94
- class ForNode
95
- def translate_statement
96
- loop_header = "for (#{iterator_identifier.to_s} = #{range_from.translate_expression}; #{iterator_identifier.to_s} <= #{range_to.translate_expression}; #{iterator_identifier.to_s}++)"
97
- loop_header + "\n" + body_stmts.translate_statement + "#{iterator_identifier.to_s}--;\n"
98
- end
99
-
100
- def translate_expression
101
- # TODO: return value should be range
102
- loop_header = "for (#{iterator_identifier.to_s} = #{range_from.translate_expression}; #{iterator_identifier.to_s} <= #{range_to.translate_expression}; #{iterator_identifier.to_s}++)"
103
- full_loop = loop_header + "\n" + body_stmts.translate_statement + "#{iterator_identifier.to_s}--;\nreturn 0;"
104
- statements_as_expression(full_loop)
105
- end
106
- end
107
-
108
- class BreakNode
109
- def translate_expression
110
- raise "Not implemented yet"
111
- end
112
-
113
- def translate_statement
114
- "break;\n"
115
- end
116
- end
117
-
118
- class IfNode
119
- def translate_statement
120
- header = "if (#{condition.translate_expression})\n"
121
-
122
- if false_body_stmts == nil
123
- header + true_body_stmts.translate_statement
124
- else
125
- header + true_body_stmts.translate_statement + "else\n" + false_body_stmts.translate_statement
126
- end
127
- end
128
-
129
- def translate_expression
130
- header = "if (#{condition.translate_expression})\n"
131
- true_body_translated = nil
132
- false_body_translated = nil
133
-
134
- if true_body_stmts.is_begin_node?
135
- true_body_translated = true_body_stmts.translate_statement_last_returns
136
- else
137
- true_body_translated = "return " + true_body_stmts.translate_expression + ";\n"
138
- end
139
-
140
- if false_body_stmts != nil
141
- # Can be begin node or anything else
142
- if false_body_stmts.is_begin_node?
143
- false_body_translated = false_body_stmts.translate_statement_last_returns
144
- else
145
- false_body_translated = "return " + false_body_stmts.translate_expression + ";\n"
146
- end
147
- end
148
-
149
- if false_body_translated == nil
150
- statements_as_expression(header + true_body_translated)
151
- else
152
- statements_as_expression(header + true_body_translated + "else\n" + false_body_translated)
153
- end
154
- end
155
- end
156
-
157
- class BeginNode
158
- def translate_statement
159
- if body_stmts.size == 0
160
- return ""
161
- end
162
-
163
- body_translated = body_stmts.map do |stmt|
164
- stmt.translate_statement
165
- end.join("")
166
-
167
- wrap_in_c_block(body_translated)
168
- end
169
-
170
- def translate_statement_last_returns
171
- if body_stmts.size == 0
172
- raise "Cannot return empty BeginNode"
173
- end
174
-
175
- body_translated = BeginNode.new(body_stmts[0...-1]).translate_statement
176
- body_translated + "return #{body_stmts.last.translate_expression};\n"
177
- wrap_in_c_block(body_translated)
178
- end
179
-
180
- def translate_expression
181
- if body_stmts.size == 0
182
- raise "Empty BeginNode cannot be an expression"
183
- elsif body_stmts.size == 1
184
- # Preserve brackets
185
- "(#{body_stmts.first.translate_expression})"
186
- else
187
- # Wrap in lambda
188
- # Do not worry about scope of varibles, they will all be declared at the beginning of the function
189
- statements_as_expression(translate_statement_last_returns)
190
- end
191
- end
192
- end
193
-
194
- class SendNode
195
- BinarySelectors = [:+, :-, :*, :/, :%, :<, :<=, :>, :>=, :==, :!=, :&, :'&&', :|, :'||', :^]
196
-
197
- def translate_expression
198
- if BinarySelectors.include?(selector)
199
- if arguments.size != 1
200
- raise "Expected 1 argument for binary selector (#{arguments.size} given)"
201
- end
202
-
203
- "(#{receiver.translate_expression} #{selector.to_s} #{arguments.first.translate_expression})"
204
- else
205
- if receiver.get_type.is_singleton? and
206
- receiver.get_type.singleton_type.to_ruby_type.singleton_methods.include?(("_ikra_c_" + selector.to_s).to_sym)
207
- # TODO: support multiple types for receiver
208
- receiver.get_type.singleton_type.to_ruby_type.send(("_ikra_c_" + selector.to_s).to_sym, receiver.translate_expression)
209
- else
210
- # TODO: generate argument code only once
211
-
212
- if receiver.get_type.is_singleton?
213
- self_argument = []
214
- if receiver.get_type.singleton_type.should_generate_type?
215
- self_argument = [receiver]
216
- end
217
-
218
- args = ([Translator::Constants::ENV_IDENTIFIER] + (self_argument + arguments).map do |arg|
219
- arg.translate_expression
220
- end).join(", ")
221
-
222
- "#{receiver.get_type.singleton_type.mangled_method_name(selector)}(#{args})"
223
- else
224
- # Polymorphic case
225
- # TODO: This is not an expression anymore!
226
- poly_id = temp_identifier_id
227
- receiver_identifier = "_polytemp_recv_#{poly_id}"
228
- result_identifier = "_polytemp_result_#{poly_id}"
229
- header = "#{define_assign_variable(receiver_identifier, receiver)}\n#{get_type.to_c_type} #{result_identifier};\nswitch (#{receiver_identifier}.class_id)\n"
230
- case_statements = []
231
-
232
- receiver.get_type.types.each do |type|
233
- self_argument = []
234
- if type.should_generate_type?
235
- # No need to pass type as subtypes are regarded as entirely new types
236
- self_argument = ["#{receiver_identifier}.object_id"]
237
- end
238
-
239
- args = ([Translator::Constants::ENV_IDENTIFIER] + self_argument + arguments.map do |arg|
240
- arg.translate_expression
241
- end).join(", ")
242
-
243
- case_statements.push("case #{type.class_id}: #{result_identifier} = #{type.mangled_method_name(selector)}(#{args}); break;")
244
- end
245
-
246
- # TODO: compound statements only work with the GNU C++ compiler
247
- "(" + wrap_in_c_block(header + wrap_in_c_block(case_statements.join("\n")) + result_identifier + ";")[0..-2] + ")"
248
- end
249
- end
250
- end
251
- end
252
- end
253
-
254
- class ReturnNode
255
- def translate_expression
256
- raise "ReturnNode is never an expression"
257
- end
258
-
259
- def translate_statement
260
- "return #{value.translate_expression};\n"
261
- end
262
- end
263
- end
264
- end
@@ -1,28 +0,0 @@
1
- extern "C" EXPORT /*{result_type}*/ *launch_kernel(environment_t */*{host_env}*/)
2
- {
3
- printf("kernel launched\n");
4
-
5
- /* Modify host environment to contain device pointers addresses */
6
- /*{copy_env}*/
7
-
8
- /* Allocate device environment and copy over struct */
9
- environment_t */*{dev_env}*/;
10
- checkCudaErrors(cudaMalloc(&/*{dev_env}*/, sizeof(environment_t)));
11
- checkCudaErrors(cudaMemcpy(/*{dev_env}*/, /*{host_env}*/, sizeof(environment_t), cudaMemcpyHostToDevice));
12
-
13
- /*{result_type}*/ *host_result = (/*{result_type}*/ *) malloc(sizeof(/*{result_type}*/) * /*{result_size}*/);
14
- /*{result_type}*/ *device_result;
15
- checkCudaErrors(cudaMalloc(&device_result, sizeof(/*{result_type}*/) * /*{result_size}*/));
16
-
17
- dim3 dim_grid(/*{grid_dim[0]}*/, /*{grid_dim[1]}*/, /*{grid_dim[2]}*/);
18
- dim3 dim_block(/*{block_dim[0]}*/, /*{block_dim[1]}*/, /*{block_dim[2]}*/);
19
-
20
- kernel<<<dim_grid, dim_block>>>(/*{dev_env}*/, device_result);
21
-
22
- checkCudaErrors(cudaThreadSynchronize());
23
-
24
- checkCudaErrors(cudaMemcpy(host_result, device_result, sizeof(/*{result_type}*/) * /*{result_size}*/, cudaMemcpyDeviceToHost));
25
- checkCudaErrors(cudaFree(/*{dev_env}*/));
26
-
27
- return host_result;
28
- }
@@ -1,166 +0,0 @@
1
- require "set"
2
- require_relative "types/union_type"
3
-
4
- class Frame < Hash
5
- def function_frame!
6
- @is_function_frame = true
7
- end
8
-
9
- def is_function_frame?
10
- @is_function_frame ||= false
11
- @is_function_frame
12
- end
13
-
14
- def add_return_type(type)
15
- if not is_function_frame?
16
- raise "Return type allowed only for function frames"
17
- end
18
-
19
- if not type.is_union_type?
20
- raise "Expected union type"
21
- end
22
-
23
- @return_type ||= Ikra::Types::UnionType.new
24
- @return_type.expand(type)
25
- end
26
-
27
- def return_type
28
- if not is_function_frame?
29
- raise "Return type allowed only for function frames"
30
- end
31
-
32
- @return_type ||= Ikra::Types::UnionType.new
33
- @return_type
34
- end
35
-
36
- def variable_names
37
- keys
38
- end
39
- end
40
-
41
- class Scope < Array
42
- class Variable
43
- attr_reader :type
44
- attr_accessor :read
45
- attr_accessor :written
46
-
47
- def initialize(type = Ikra::Types::UnionType.new)
48
- @type = type
49
- @read = false
50
- @written = false
51
- end
52
- end
53
-
54
- def top_frame
55
- last
56
- end
57
-
58
- def previous_frame
59
- self[-2]
60
- end
61
-
62
- def push_frame
63
- frame = Frame.new
64
- frame.default_proc = Proc.new do |hash, key|
65
- hash[key] = Variable.new
66
- end
67
- push(frame)
68
- end
69
-
70
- def push_function_frame
71
- push_frame
72
- top_frame.function_frame!
73
- end
74
-
75
- def pop_frame
76
- pop
77
- end
78
-
79
- # TODO: maybe remove?
80
- def define_shadowed(name, type)
81
- if top_frame.has_key?(name)
82
- raise "#{name} already defined"
83
- end
84
-
85
- top_frame[name] = Variable.new(type)
86
- end
87
-
88
- def is_defined?(name)
89
- any? do |frame|
90
- frame.has_key?(name)
91
- end
92
- end
93
-
94
- def get_type(name)
95
- reverse_each do |frame|
96
- if frame.has_key?(name)
97
- return frame[name].type
98
- end
99
- end
100
-
101
- raise "#{name} not found in symbol table"
102
- end
103
-
104
- def declare_expand_type(name, type)
105
- if not type.is_union_type?
106
- raise "Expected union type"
107
- end
108
-
109
- top_frame[name].type.expand(type)
110
- end
111
-
112
- def add_return_type(type)
113
- reverse_each.detect do |fr|
114
- fr.add_return_type(type)
115
- return self
116
- end
117
-
118
- raise "Function frame not found"
119
- end
120
-
121
- def read!(name)
122
- frame = reverse_each.detect do |fr|
123
- fr.has_key?(name)
124
- end
125
-
126
- frame[name].read = true
127
- end
128
-
129
- def written!(name)
130
- frame = reverse_each.detect do |fr|
131
- fr.has_key?(name)
132
- end
133
-
134
- frame[name].written = true
135
- end
136
-
137
- def read_variables(frame_position)
138
- frame = self[frame_position]
139
- frame.select do |name, var|
140
- var.read
141
- end.keys
142
- end
143
-
144
- def written_variables(frame_position)
145
- frame = self[frame_position]
146
- frame.select do |name, var|
147
- var.written
148
- end.keys
149
- end
150
-
151
- def read_and_written_variables(frame_position = -1)
152
- read_variables(frame_position) + written_variables(frame_position)
153
- end
154
-
155
- def new_frame(&block)
156
- push_frame
157
- yield
158
- pop_frame
159
- end
160
-
161
- def new_function_frame(&block)
162
- push_function_frame
163
- yield
164
- pop_frame
165
- end
166
- end