carbon-core 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +38 -0
  5. data/.travis.yml +4 -0
  6. data/.yardopts +1 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +11 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +41 -0
  11. data/Rakefile +14 -0
  12. data/carbon.gemspec +30 -0
  13. data/lib/carbon.rb +54 -0
  14. data/lib/carbon/concrete.rb +43 -0
  15. data/lib/carbon/concrete/build.rb +63 -0
  16. data/lib/carbon/concrete/index.rb +324 -0
  17. data/lib/carbon/concrete/item.rb +37 -0
  18. data/lib/carbon/concrete/item/base.rb +153 -0
  19. data/lib/carbon/concrete/item/data.rb +22 -0
  20. data/lib/carbon/concrete/item/function.rb +97 -0
  21. data/lib/carbon/concrete/item/internal.rb +83 -0
  22. data/lib/carbon/concrete/item/struct.rb +65 -0
  23. data/lib/carbon/concrete/item/struct/element.rb +42 -0
  24. data/lib/carbon/concrete/item/trait.rb +72 -0
  25. data/lib/carbon/concrete/item/trait/expectation.rb +55 -0
  26. data/lib/carbon/concrete/request.rb +137 -0
  27. data/lib/carbon/concrete/type.rb +260 -0
  28. data/lib/carbon/concrete/type/function.rb +91 -0
  29. data/lib/carbon/concrete/type/generic.rb +118 -0
  30. data/lib/carbon/concrete/type/name.rb +147 -0
  31. data/lib/carbon/concrete/type/parse.rb +172 -0
  32. data/lib/carbon/concrete/type/part.rb +100 -0
  33. data/lib/carbon/core.rb +61 -0
  34. data/lib/carbon/core/int.rb +87 -0
  35. data/lib/carbon/core/integer.rb +109 -0
  36. data/lib/carbon/core/integer/cast.rb +83 -0
  37. data/lib/carbon/core/integer/math.rb +198 -0
  38. data/lib/carbon/core/integer/misc.rb +145 -0
  39. data/lib/carbon/core/integer/pole.rb +133 -0
  40. data/lib/carbon/core/integer/ship.rb +71 -0
  41. data/lib/carbon/core/integer/sign.rb +52 -0
  42. data/lib/carbon/core/integer/type.rb +42 -0
  43. data/lib/carbon/core/integer/zero.rb +52 -0
  44. data/lib/carbon/core/pointer.rb +54 -0
  45. data/lib/carbon/core/pointer/access.rb +123 -0
  46. data/lib/carbon/core/pointer/cast.rb +55 -0
  47. data/lib/carbon/core/pointer/math.rb +187 -0
  48. data/lib/carbon/core/pointer/memory.rb +85 -0
  49. data/lib/carbon/core/pointer/type.rb +23 -0
  50. data/lib/carbon/tacky.rb +21 -0
  51. data/lib/carbon/tacky/block.rb +96 -0
  52. data/lib/carbon/tacky/builder.rb +310 -0
  53. data/lib/carbon/tacky/context.rb +66 -0
  54. data/lib/carbon/tacky/function.rb +137 -0
  55. data/lib/carbon/tacky/instruction.rb +170 -0
  56. data/lib/carbon/tacky/parameter.rb +23 -0
  57. data/lib/carbon/tacky/reference.rb +23 -0
  58. data/lib/carbon/tacky/value.rb +40 -0
  59. data/lib/carbon/version.rb +9 -0
  60. metadata +186 -0
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Carbon
5
+ module Core
6
+ module Pointer
7
+ # Defines the pointer type.
8
+ module Type
9
+ # Defines the pointer type, setting it to implement both
10
+ # `Carbon::Sized` and `Carbon::Numeric`.
11
+ #
12
+ # @return [void]
13
+ def define_pointer_type
14
+ Core.define(internal: PTYPE) do |internal|
15
+ internal[:kind] = :pointer
16
+ internal[:implements] << Carbon::Type("Carbon::Sized")
17
+ internal[:implements] << Carbon::Type("Carbon::Numeric")
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require "carbon/tacky/block"
5
+ require "carbon/tacky/builder"
6
+ require "carbon/tacky/context"
7
+ require "carbon/tacky/function"
8
+ require "carbon/tacky/value"
9
+ require "carbon/tacky/instruction"
10
+ require "carbon/tacky/parameter"
11
+ require "carbon/tacky/reference"
12
+
13
+ module Carbon
14
+ # Tacky is a IR implementation. It is a medium-level IR, just above LLVM IR
15
+ # and just below Carbon. It is here in order to easily serialize the
16
+ # results of compiling a Carbon file without loosing generic information,
17
+ # which is essential for building everything else. Tacky is meant to be
18
+ # easily serialized and deserialized, to allow libraries to be created.
19
+ module Tacky
20
+ end
21
+ end
@@ -0,0 +1,96 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Carbon
5
+ module Tacky
6
+ # Defines a "block" in Tacky. This corresponds to LLVM's "basic block" for
7
+ # functions. This only contains a list of instructions and a name, and
8
+ # can be referenced by that name.
9
+ class Block
10
+ # A list of instructions that are executed by this block. This
11
+ # shoudln't be directly modified, and instead should be modified via
12
+ # {#build}.
13
+ #
14
+ # @return [<Tacky::Instruction>]
15
+ attr_reader :instructions
16
+
17
+ # The "name" of the block. This is used to make the resulting LLVM IR
18
+ # more legible.
19
+ #
20
+ # @return [::String]
21
+ attr_reader :name
22
+
23
+ # Temporarily used during building to store the mapping of instruction
24
+ # ids to their LLVM counterparts.
25
+ #
26
+ # @return [{::Numeric => ::LLVM::Value}]
27
+ attr_reader :mapping
28
+
29
+ # Initializes the block with the given name and instructions. If
30
+ # no name is given, it defaults to an empty string (`""`). Instructions
31
+ # should not be passed by initialization.
32
+ #
33
+ # @param function [Tacky::Function] The function this block is a part
34
+ # of.
35
+ # @param name [::String] The name of the block.
36
+ # @param instructions [<Tacky::Instruction>] This should not be used.
37
+ def initialize(function, name = "", instructions = [])
38
+ @function = function
39
+ @name = name
40
+ @instructions = instructions
41
+ end
42
+
43
+ # Increment the function's counter, returning the next valid instruction
44
+ # id.
45
+ #
46
+ # @return [::Numeric]
47
+ def next
48
+ @function.counter.increment
49
+ end
50
+
51
+ # Retrieves the dependencies that the block has. This is determined by
52
+ # asking any of the instructions if they have any dependencies, returning
53
+ # an empty set if all of them have none.
54
+ #
55
+ # @api private
56
+ # @see Function#dependencies
57
+ # @see Instruction#dependencies
58
+ # @return [Set<Concrete::Type>] The dependencies of the block.
59
+ def dependencies
60
+ @instructions.map(&:dependencies).inject(Set.new, :merge)
61
+ end
62
+
63
+ # Builds the block with the given context. This iterates over all of
64
+ # the instructions, calling them, and storing the results in the function
65
+ # instruction table ({Tacky::Context#instructions}).
66
+ #
67
+ # @api private
68
+ # @see Instruction#call
69
+ # @see Context#instructions
70
+ # @param context [Tacky::Context] The context to build with.
71
+ # @return [void]
72
+ def call(context)
73
+ this = context.blocks.fetch(self)
74
+
75
+ @instructions.each do |inst|
76
+ context.instructions[inst.value] = inst.call(context, this)
77
+ end
78
+ end
79
+
80
+ # Builds the block. If a block is given, it yields a {Tacky::Builder};
81
+ # otherwise, it returns one.
82
+ #
83
+ # @yield [builder] To build the block.
84
+ # @yieldparam builder [Tacky::Builder] The builder.
85
+ # @return [Tacky::Builder] If no block was given.
86
+ # @return [::Object] Otherwise.
87
+ def build
88
+ if block_given?
89
+ yield Tacky::Builder.new(self)
90
+ else
91
+ Tacky::Builder.new(self)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,310 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Carbon
5
+ module Tacky
6
+ # A "builder." This is used in order to create an instruction set for a
7
+ # block. The builder defines a set of methods that create and append
8
+ # an instruction to the parent block. Each instruction gets its own
9
+ # instruction ID relative to the parent block.
10
+ #
11
+ # @see http://llvm.org/releases/3.5.2/docs/LangRef.html The LLVM Language
12
+ # Reference Manual.
13
+ # @api semiprivate
14
+ class Builder
15
+ # Initialize the builder with the given block.
16
+ #
17
+ # @param block [Tacky::Block] The block to build onto.
18
+ def initialize(block)
19
+ @block = block
20
+ end
21
+
22
+ methods = ::LLVM::Builder.instance_methods - Object.instance_methods -
23
+ %i(dispose insert_block position position_at_end
24
+ position_before to_ptr)
25
+
26
+ # @!method add(left, right, name = "")
27
+ # Creates an `add` instruction.
28
+ # @return [Tacky::Reference]
29
+ # @!method aggregate_ret(*values)
30
+ # Creates a `ret` instruction.
31
+ # @return [Tacky::Reference]
32
+ # @!method alloca(type, name = "")
33
+ # Creates an `alloca` instruction.
34
+ # @return [Tacky::Reference]
35
+ # @!method and(left, right, name = "")
36
+ # Creates an `and` instruction.
37
+ # @return [Tacky::Reference]
38
+ # @!method array_alloca(type, size, name = "")
39
+ # Creates an `array_alloca` instruction.
40
+ # @return [Tacky::Reference]
41
+ # @!method ashr(left, right, name = "")
42
+ # Creates an `ashr` instruction.
43
+ # @return [Tacky::Reference]
44
+ # @!method bit_cast(value, type, name = "")
45
+ # Creates a `bitcast` instruction.
46
+ # @return [Tacky::Reference]
47
+ # @!method br(destination)
48
+ # Creates a `br` instruction.
49
+ # @return [Tacky::Reference]
50
+ # @!method call(function, *arguments)
51
+ # Creates a `call` instruction.
52
+ # @return [Tacky::Reference]
53
+ # @!method cond(iftrue, iffalse)
54
+ # Creates a `br` instruction.
55
+ # @return [Tacky::Reference]
56
+ # @!method exact_sdiv(left, right, name = "")
57
+ # Creates an `sdiv` instruction.
58
+ # @return [Tacky::Reference]
59
+ # @!method extract_element(vector, index, name = "")
60
+ # Creates an `extract_element` instruction.
61
+ # @return [Tacky::Reference]
62
+ # @!method extract_value(aggregate, index, name = "")
63
+ # Creates an `extract_value` instruction.
64
+ # @return [Tacky::Reference]
65
+ # @!method fadd(left, right, name = "")
66
+ # Creates an `fadd` instruction.
67
+ # @return [Tacky::Reference]
68
+ # @!method fcmp(pred, left, right, name = "")
69
+ # Creates an `fcmp` instruction.
70
+ # @return [Tacky::Reference]
71
+ # @!method fdiv(left, right, name = "")
72
+ # Creates an `fdiv` instruction.
73
+ # @return [Tacky::Reference]
74
+ # @!method fmul(left, right, name = "")
75
+ # Creates an `fmul` instruction.
76
+ # @return [Tacky::Reference]
77
+ # @!method fp2si(value, type, name = "")
78
+ # Creates a `fptosi` instruction.
79
+ # @return [Tacky::Reference]
80
+ # @!method fp2ui(value, type, name = "")
81
+ # Creates a `fptoui` instruction.
82
+ # @return [Tacky::Reference]
83
+ # @!method fp_cast(value, type, name = "")
84
+ # Creates a `bitcast` instruction.
85
+ # @return [Tacky::Reference]
86
+ # @!method fp_ext(value, type, name = "")
87
+ # Creates a `fpext` instruction.
88
+ # @return [Tacky::Reference]
89
+ # @!method fp_trunc(value, type, name = "")
90
+ # Creates a `fptrunc` instruction.
91
+ # @return [Tacky::Reference]
92
+ # @!method free(pointer)
93
+ # Creates a `free` instruction.
94
+ # @return [Tacky::Reference]
95
+ # @!method frem(left, right, name = "")
96
+ # Creates a `frem` instruction.
97
+ # @return [Tacky::Reference]
98
+ # @!method fsub(left, right, name = "")
99
+ # Creates a `fsub` instruction.
100
+ # @return [Tacky::Reference]
101
+ # @!method gep(value, indices, name = "")
102
+ # Creates a `gep` instruction.
103
+ # @return [Tacky::Reference]
104
+ # @!method global_string(string, name = "")
105
+ # Creates a `global_string` instruction.
106
+ # @return [Tacky::Reference]
107
+ # @!method global_string_pointer(string, name = "")
108
+ # Creates a `global_string_pointer` instruction.
109
+ # @return [Tacky::Reference]
110
+ # @!method ibr(addr, destinations)
111
+ # Creates a `ibr` instruction.
112
+ # @return [Tacky::Reference]
113
+ # @!method icmp(pred, left, right, name = "")
114
+ # Creates an `icmp` instruction.
115
+ # @return [Tacky::Reference]
116
+ # @!method inbounds_gep(value, indices, name = "")
117
+ # Creates an `gep` instruction.
118
+ # @return [Tacky::Reference]
119
+ # @!method insert_element(vector, value, index, name = "")
120
+ # Creates an `insert_element` instruction.
121
+ # @return [Tacky::Reference]
122
+ # @!method insert_value(aggregate, value, index, name = "")
123
+ # Creates an `insert_value` instruction.
124
+ # @return [Tacky::Reference]
125
+ # @!method int2ptr(value, type, name = "")
126
+ # Creates an `inttoptr` instruction.
127
+ # @return [Tacky::Reference]
128
+ # @!method int_cast(value, type, name = "")
129
+ # Creates an `bitcast` instruction.
130
+ # @return [Tacky::Reference]
131
+ # @!method invoke(function, params, normal, exception, name = "")
132
+ # Creates an `invoke` instruction.
133
+ # @return [Tacky::Reference]
134
+ # @!method is_not_null(value, name = "")
135
+ # Creates an `is_not_null` instruction.
136
+ # @return [Tacky::Reference]
137
+ # @!method is_null(value, name = "")
138
+ # Creates an `is_null` instruction.
139
+ # @return [Tacky::Reference]
140
+ # @!method load(pointer, name = "")
141
+ # Creates a `load` instruction.
142
+ # @return [Tacky::Reference]
143
+ # @!method lshr(left, right, name = "")
144
+ # Creates a `lshr` instruction.
145
+ # @return [Tacky::Reference]
146
+ # @!method malloc(type, name = "")
147
+ # Creates a `malloc` instruction.
148
+ # @return [Tacky::Reference]
149
+ # @!method mul(left, right, name = "")
150
+ # Creates a `mul` instruction.
151
+ # @return [Tacky::Reference]
152
+ # @!method neg(value, name = "")
153
+ # Creates a `sub` instruction.
154
+ # @return [Tacky::Reference]
155
+ # @!method not(value, name = "")
156
+ # Creates a `not` instruction.
157
+ # @return [Tacky::Reference]
158
+ # @!method nsw_add(left, right, name = "")
159
+ # Creates an `add` instruction.
160
+ # @return [Tacky::Reference]
161
+ # @!method nsw_mul(left, right, name = "")
162
+ # Creates a `mul` instruction.
163
+ # @return [Tacky::Reference]
164
+ # @!method nsw_neg(left, right, name = "")
165
+ # Creates a `sub` instruction.
166
+ # @return [Tacky::Reference]
167
+ # @!method nsw_sub(left, right, name = "")
168
+ # Creates a `sub` instruction.
169
+ # @return [Tacky::Reference]
170
+ # @!method nuw_add(left, right, name = "")
171
+ # Creates an `add` instruction.
172
+ # @return [Tacky::Reference]
173
+ # @!method nuw_mul(left, right, name = "")
174
+ # Creates a `mul` instruction.
175
+ # @return [Tacky::Reference]
176
+ # @!method nuw_neg(left, right, name = "")
177
+ # Creates a `sub` instruction.
178
+ # @return [Tacky::Reference]
179
+ # @!method nuw_sub(left, right, name = "")
180
+ # Creates a `sub` instruction.
181
+ # @return [Tacky::Reference]
182
+ # @!method or(left, right, name = "")
183
+ # Creates an `or` instruction.
184
+ # @return [Tacky::Reference]
185
+ # @!method phi(type, incoming, name = "")
186
+ # Creates a `phi` instruction.
187
+ # @return [Tacky::Reference]
188
+ # @!method pointer_cast(value, type, name = "")
189
+ # Creates a `bitcast` instruction.
190
+ # @return [Tacky::Reference]
191
+ # @!method ptr2int(value, type, name = "")
192
+ # Creates a `ptrtoint` instruction.
193
+ # @return [Tacky::Reference]
194
+ # @!method ptr_diff(left, right, name = "")
195
+ # Creates a `ptr_diff` instruction.
196
+ # @return [Tacky::Reference]
197
+ # @!method ret(value)
198
+ # Creates a `ret` instruction.
199
+ # @return [Tacky::Reference]
200
+ # @!method ret_void(value)
201
+ # Creates a `ret` instruction.
202
+ # @return [Tacky::Reference]
203
+ # @!method sdiv(left, right, name = "")
204
+ # Creates an `sdiv` instruction.
205
+ # @return [Tacky::Reference]
206
+ # @!method select(check, vtrue, vfalse, name = "")
207
+ # Creates a `select` instruction.
208
+ # @return [Tacky::Reference]
209
+ # @!method sext(value, type, name = "")
210
+ # Creates a `sext` instruction.
211
+ # @return [Tacky::Reference]
212
+ # @!method sext_or_bit_cast(value, type, name = "")
213
+ # Creates a `sext` or `bitcast` instruction, depending on the value
214
+ # and type.
215
+ # @return [Tacky::Reference]
216
+ # @!method shl(left, right, name = "")
217
+ # Creates a `shl` instruction.
218
+ # @return [Tacky::Reference]
219
+ # @!method shuffle_vector(vec1, vec2, mask, name = "")
220
+ # Creates a `shuffle_vector` instruction.
221
+ # @return [Tacky::Reference]
222
+ # @!method si2fp(value, type, name = "")
223
+ # Creates a `sitofp` instruction.
224
+ # @return [Tacky::Reference]
225
+ # @!method srem(left, right, name = "")
226
+ # Creates a `srem` instruction.
227
+ # @return [Tacky::Reference]
228
+ # @!method store(pointer, value)
229
+ # Creates a `store` instruction.
230
+ # @return [Tacky::Reference]
231
+ # @!method struct_gep(value, index, name = "")
232
+ # Creates a `gep` instruction.
233
+ # @return [Tacky::Reference]
234
+ # @!method sub(left, right, name = "")
235
+ # Creates a `sub` instruction.
236
+ # @return [Tacky::Reference]
237
+ # @!method switch(value, default, cases)
238
+ # Creates a `switch` instruction.
239
+ # @return [Tacky::Reference]
240
+ # @!method trunc(value, type, name = "")
241
+ # Creates a `trunc` instruction.
242
+ # @return [Tacky::Reference]
243
+ # @!method trunc_or_bit_cast(value, type, name = "")
244
+ # Creates a `trunc` or `bitcast` instruction based on the value and
245
+ # type.
246
+ # @return [Tacky::Reference]
247
+ # @!method udiv(left, right, name = "")
248
+ # Creates a `udiv` instruction.
249
+ # @return [Tacky::Reference]
250
+ # @!method ui2fp(value, type, name = "")
251
+ # Creates a `uitofp` instruction.
252
+ # @return [Tacky::Reference]
253
+ # @!method unreachable
254
+ # Creates an `unreachable` instruction.
255
+ # @return [Tacky::Reference]
256
+ # @!method unwind
257
+ # Creates an `unwind` instruction.
258
+ # @return [Tacky::Reference]
259
+ # @!method urem(left, right, name = "")
260
+ # Creates a `urem` instruction.
261
+ # @return [Tacky::Reference]
262
+ # @!method zext(value, type, name = "")
263
+ # Creates a `zext` instruction.
264
+ # @return [Tacky::Reference]
265
+ # @!method zext_or_bit_cast(value, type, name = "")
266
+ # Creates a `zext` or `bitcast` instruction based on the value and
267
+ # type.
268
+ # @return [Tacky::Reference]
269
+ methods.each { |m| define_method(m) { |*a| _call(m, *a) } }
270
+
271
+ # Returns the size of a type. This may be a constant value or a
272
+ # generated value.
273
+ #
274
+ # @param type [Concrete::Type] The type to find the size of.
275
+ # @return [Tacky::Reference] A value representing the return value of
276
+ # the instruction.
277
+ def sizeof(type)
278
+ _call(:_sizeof, type)
279
+ end
280
+
281
+ # Returns a null value of a given type. This may be a constant value or a
282
+ # generated value.
283
+ #
284
+ # @param type [Concrete::Type] The type to null.
285
+ # @return [Tacky::Reference] A value representing the return value of
286
+ # the instruction.
287
+ def null(type)
288
+ _call(:_null, type)
289
+ end
290
+
291
+ # Creates an instruction, and returns a reference to that instruction.
292
+ # The reference points to the instruction using the "instruction id,"
293
+ # which is essentially the instruction's place in the block.
294
+ #
295
+ # @api private
296
+ # @param inst [::Symbol, ::String] The instruction name.
297
+ # @param parameters [<Reference, Parameter, Value, Object>] The
298
+ # parameters that are being passed to the instruction.
299
+ # @param name [::String] The return value name of the instruction.
300
+ # @return [Tacky::Reference] The reference to the new instruction.
301
+ def _call(inst, *parameters, name: "")
302
+ id = @block.next
303
+ instruction = Tacky::Instruction.new(id, inst, parameters)
304
+ instruction.name = name
305
+ @block.instructions << instruction
306
+ Tacky::Reference.new(id)
307
+ end
308
+ end
309
+ end
310
+ end