carbon-core 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.
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