carbon-core 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -2
  3. data/.rspec +0 -0
  4. data/.rubocop.yml +0 -0
  5. data/.travis.yml +0 -0
  6. data/.yardopts +0 -0
  7. data/CODE_OF_CONDUCT.md +0 -0
  8. data/Gemfile +0 -0
  9. data/LICENSE.txt +0 -0
  10. data/README.md +0 -0
  11. data/Rakefile +0 -0
  12. data/Vagrantfile +83 -0
  13. data/carbon.gemspec +1 -1
  14. data/lib/carbon.rb +3 -2
  15. data/lib/carbon/concrete.rb +0 -0
  16. data/lib/carbon/concrete/build.rb +1 -1
  17. data/lib/carbon/concrete/index.rb +37 -13
  18. data/lib/carbon/concrete/item.rb +0 -0
  19. data/lib/carbon/concrete/item/base.rb +11 -0
  20. data/lib/carbon/concrete/item/data.rb +0 -0
  21. data/lib/carbon/concrete/item/function.rb +13 -1
  22. data/lib/carbon/concrete/item/internal.rb +0 -0
  23. data/lib/carbon/concrete/item/struct.rb +0 -0
  24. data/lib/carbon/concrete/item/struct/element.rb +0 -0
  25. data/lib/carbon/concrete/item/trait.rb +0 -0
  26. data/lib/carbon/concrete/item/trait/expectation.rb +0 -0
  27. data/lib/carbon/concrete/request.rb +0 -0
  28. data/lib/carbon/concrete/type.rb +0 -0
  29. data/lib/carbon/concrete/type/function.rb +0 -0
  30. data/lib/carbon/concrete/type/generic.rb +0 -0
  31. data/lib/carbon/concrete/type/name.rb +0 -0
  32. data/lib/carbon/concrete/type/parse.rb +0 -0
  33. data/lib/carbon/concrete/type/part.rb +0 -0
  34. data/lib/carbon/core.rb +1 -1
  35. data/lib/carbon/core/int.rb +0 -0
  36. data/lib/carbon/core/integer.rb +0 -0
  37. data/lib/carbon/core/integer/cast.rb +4 -4
  38. data/lib/carbon/core/integer/math.rb +11 -10
  39. data/lib/carbon/core/integer/misc.rb +6 -5
  40. data/lib/carbon/core/integer/pole.rb +9 -7
  41. data/lib/carbon/core/integer/ship.rb +4 -2
  42. data/lib/carbon/core/integer/sign.rb +0 -0
  43. data/lib/carbon/core/integer/type.rb +0 -0
  44. data/lib/carbon/core/integer/zero.rb +2 -2
  45. data/lib/carbon/core/pointer.rb +0 -0
  46. data/lib/carbon/core/pointer/access.rb +7 -4
  47. data/lib/carbon/core/pointer/cast.rb +1 -1
  48. data/lib/carbon/core/pointer/math.rb +12 -10
  49. data/lib/carbon/core/pointer/memory.rb +4 -4
  50. data/lib/carbon/core/pointer/type.rb +0 -0
  51. data/lib/carbon/tacky.rb +1 -0
  52. data/lib/carbon/tacky/block.rb +0 -0
  53. data/lib/carbon/tacky/builder.rb +14 -2
  54. data/lib/carbon/tacky/context.rb +12 -1
  55. data/lib/carbon/tacky/function.rb +1 -1
  56. data/lib/carbon/tacky/instruction.rb +9 -54
  57. data/lib/carbon/tacky/instruction/dependencies.rb +33 -0
  58. data/lib/carbon/tacky/instruction/generation.rb +90 -0
  59. data/lib/carbon/tacky/instruction/typeof.rb +25 -0
  60. data/lib/carbon/tacky/parameter.rb +0 -0
  61. data/lib/carbon/tacky/reference.rb +4 -0
  62. data/lib/carbon/tacky/typed.rb +25 -0
  63. data/lib/carbon/tacky/value.rb +0 -0
  64. data/lib/carbon/version.rb +1 -1
  65. data/scripts/core.rb +9 -0
  66. data/scripts/test.rb +19 -0
  67. metadata +12 -5
@@ -35,7 +35,7 @@ module Carbon
35
35
  function[:definition].add("entry").build do |b|
36
36
  this = function[:definition].params[0]
37
37
  this.name = "self"
38
- b.ret(b.icmp(:ne, this, 0))
38
+ b.ret(b.icmp(:ne, this, 0).as(Carbon::Boolean))
39
39
  end
40
40
  end
41
41
  end
@@ -110,7 +110,7 @@ module Carbon
110
110
  this = definition.params[0]
111
111
  this.name = "self"
112
112
 
113
- entry.ret(entry.add(this, 1))
113
+ entry.ret(entry.add(this, 1).as(this.type))
114
114
  end
115
115
 
116
116
  def define_prev_definition(definition)
@@ -118,7 +118,7 @@ module Carbon
118
118
  this = definition.params[0]
119
119
  this.name = "self"
120
120
 
121
- entry.ret(entry.sub(this, 1))
121
+ entry.ret(entry.sub(this, 1).as(this.type))
122
122
  end
123
123
 
124
124
  def define_iabs_definition(int, definition)
@@ -129,8 +129,9 @@ module Carbon
129
129
  if int.sign == :unsigned
130
130
  entry.ret(this)
131
131
  else
132
- y = entry.ashr(this, int.size - 1)
133
- entry.ret(entry.sub(entry.xor(this, y), y))
132
+ y = entry.ashr(this, int.size - 1).as(this.type)
133
+ sub = entry.sub(entry.xor(this, y).as(this.type), y).as(this.type)
134
+ entry.ret(sub)
134
135
  end
135
136
  end
136
137
 
@@ -95,8 +95,8 @@ module Carbon
95
95
  this.name = "self"
96
96
 
97
97
  return entry.ret(1) if int.sign == :unsigned
98
- sign = entry.lshr(this, int.size - 1)
99
- trunc = entry.trunc(sign, Carbon::Boolean)
98
+ sign = entry.lshr(this, int.size - 1).as(this.type)
99
+ trunc = entry.trunc(sign, Carbon::Boolean).as(Carbon::Boolean)
100
100
  entry.ret(trunc)
101
101
  end
102
102
 
@@ -106,9 +106,9 @@ module Carbon
106
106
  this.name = "self"
107
107
 
108
108
  return entry.ret(0) if int.sign == :unsigned
109
- sign = entry.lshr(this, int.size - 1)
110
- trunc = entry.trunc(sign, Carbon::Boolean)
111
- negate = entry.xor(trunc, 1)
109
+ sign = entry.lshr(this, int.size - 1).as(this.type)
110
+ trunc = entry.trunc(sign, Carbon::Boolean).as(Carbon::Boolean)
111
+ negate = entry.xor(trunc, 1).as(Carbon::Boolean)
112
112
  entry.ret(negate)
113
113
  end
114
114
 
@@ -117,7 +117,9 @@ module Carbon
117
117
  this = definition.params[0]
118
118
  this.name = "self"
119
119
 
120
- entry.ret(entry.xor(entry.trunc(this, Carbon::Boolean), 1))
120
+ trunc = entry.trunc(this, Carbon::Boolean).as(Carbon::Boolean)
121
+ xor = entry.xor(trunc, 1).as(Carbon::Boolean)
122
+ entry.ret(xor)
121
123
  end
122
124
 
123
125
  def define_odd_definition(_int, definition)
@@ -125,7 +127,7 @@ module Carbon
125
127
  this = definition.params[0]
126
128
  this.name = "self"
127
129
 
128
- entry.ret(entry.trunc(this, Carbon::Boolean))
130
+ entry.ret(entry.trunc(this, Carbon::Boolean).as(Carbon::Boolean))
129
131
  end
130
132
  end
131
133
  end
@@ -61,9 +61,11 @@ module Carbon
61
61
 
62
62
  def define_ship_definition_compare(params, blocks)
63
63
  blocks[0]
64
- .build { |b| b.br(b.icmp(:lt, *params), blocks[1], blocks[2]) }
64
+ .build { |b| b.br(b.icmp(:lt, *params).as(Carbon::Boolean),
65
+ blocks[1], blocks[2]) }
65
66
  blocks[2]
66
- .build { |b| b.br(b.icmp(:eq, *params), blocks[4], blocks[5]) }
67
+ .build { |b| b.br(b.icmp(:eq, *params).as(Carbon::Boolean),
68
+ blocks[3], blocks[4]) }
67
69
  end
68
70
  end
69
71
  end
File without changes
File without changes
@@ -25,7 +25,7 @@ module Carbon
25
25
  function[:definition].add("entry").build do |b|
26
26
  this = function[:definition].params[0]
27
27
  this.name = "self"
28
- b.ret(b.icmp(:eq, this, 0))
28
+ b.ret(b.icmp(:eq, this, 0).as(Carbon::Boolean))
29
29
  end
30
30
  end
31
31
  end
@@ -42,7 +42,7 @@ module Carbon
42
42
  function[:definition].add("entry").build do |b|
43
43
  this = function[:definition].params[0]
44
44
  this.name = "self"
45
- b.ret(b.icmp(:ne, this, 0))
45
+ b.ret(b.icmp(:ne, this, 0).as(Carbon::Boolean))
46
46
  end
47
47
  end
48
48
  end
File without changes
@@ -84,12 +84,13 @@ module Carbon
84
84
 
85
85
  private
86
86
 
87
- def define_array_set_definition(_int, definition)
87
+ def define_array_set_definition(int, definition)
88
88
  entry = definition.add("entry").build
89
89
  this, index, value = definition.params
90
90
  this.name, index.name, value.name = %w(self index value)
91
91
 
92
- entry.store(entry.gep(this, index), value)
92
+ gep = entry.gep(this, index).as(Carbon::Type("Carbon::UInt64"))
93
+ entry.store(gep, value)
93
94
  entry.ret(value)
94
95
  end
95
96
 
@@ -98,7 +99,9 @@ module Carbon
98
99
  this, index = definition.params
99
100
  this.name, index.name = %w(self index)
100
101
 
101
- entry.ret(entry.load(entry.gep(this, index)))
102
+ gep = entry.gep(this, index).as(Carbon::Type("Carbon::UInt64"))
103
+ load = entry.load(gep).as(PTYPEGEN)
104
+ entry.ret(load)
102
105
  end
103
106
 
104
107
  def define_value_set_definition(definition)
@@ -115,7 +118,7 @@ module Carbon
115
118
  this = definition.params[0]
116
119
  this.name = "self"
117
120
 
118
- entry.ret(entry.load(this))
121
+ entry.ret(entry.load(this).as(PTYPEGEN))
119
122
  end
120
123
  end
121
124
  end
@@ -47,7 +47,7 @@ module Carbon
47
47
  this = definition.params[0]
48
48
  this.name = "self"
49
49
 
50
- entry.ret(entry.ptr2int(this, int.name))
50
+ entry.ret(entry.ptr2int(this, int.name).as(int.name))
51
51
  end
52
52
  end
53
53
  end
@@ -126,8 +126,8 @@ module Carbon
126
126
  this, other = params
127
127
  this.name, other.name = %w(self other)
128
128
  fname = PTYPE.call(int.cast, [PTYPE])
129
- thisint = entry.call(fname, this)
130
- otherint = entry.call(fname, other)
129
+ thisint = entry.call(fname, this).as(int.name)
130
+ otherint = entry.call(fname, other).as(int.name)
131
131
  [thisint, otherint]
132
132
  end
133
133
 
@@ -138,7 +138,8 @@ module Carbon
138
138
  this, other = perform_pointer_cast(entry, params, int)
139
139
 
140
140
  fname = PTYPE.call(:<=>, [int.name, int.name])
141
- entry.ret(entry.call(fname, this, other))
141
+ call = entry.call(fname, this, other)
142
+ entry.ret(call.as(Carbon::Type("Carbon::Int8")))
142
143
  end
143
144
 
144
145
  def define_comp_pointer_definition(op, definition)
@@ -148,7 +149,7 @@ module Carbon
148
149
  this, other = perform_pointer_cast(entry, params, int)
149
150
  icmp = Integer::Math::COMP_OPERATIONS_MAP.fetch([:signed, op])
150
151
 
151
- entry.ret(entry.icmp(icmp, this, other))
152
+ entry.ret(entry.icmp(icmp, this, other).as(Carbon::Boolean))
152
153
  end
153
154
 
154
155
  def define_space_definition(int, definition)
@@ -157,9 +158,10 @@ module Carbon
157
158
  this.name, other.name = %w(self other)
158
159
 
159
160
  fname = PTYPE.call(int.cast, [PTYPE])
160
- intptr = entry.call(fname, this)
161
+ intptr = entry.call(fname, this).as(int.name)
161
162
  fname = PTYPE.call(:<=>, [int.name, int.name])
162
- entry.ret(entry.call(fname, intptr, other))
163
+ compare = entry.call(fname, intptr, other)
164
+ entry.ret(compare.as(Carbon::Type("Carbon::Int8")))
163
165
  end
164
166
 
165
167
  def define_comp_definition(int, op, definition)
@@ -168,18 +170,18 @@ module Carbon
168
170
  this.name, other.name = %w(self other)
169
171
 
170
172
  fname = PTYPE.call(int.cast, [PTYPE])
171
- intptr = entry.call(fname, this)
173
+ intptr = entry.call(fname, this).as(int.name)
172
174
  icmp = Integer::Math::COMP_OPERATIONS_MAP.fetch([int.sign, op])
173
- entry.ret(entry.icmp(icmp, intptr, other))
175
+ entry.ret(entry.icmp(icmp, intptr, other).as(Carbon::Boolean))
174
176
  end
175
177
 
176
178
  def define_math_definition(_int, op, definition)
177
179
  entry = definition.add("entry").build
178
180
  this, other = definition.params
179
181
  this.name, other.name = %w(self other)
180
- other = entry.mul(other, -1) if op == :-
182
+ other = entry.mul(other, -1).as(other.type) if op == :-
181
183
 
182
- entry.ret(entry.gep(this, other))
184
+ entry.ret(entry.gep(this, other).as(PTYPE))
183
185
  end
184
186
  end
185
187
  end
@@ -60,10 +60,10 @@ module Carbon
60
60
  size = definition.params[0]
61
61
  size.name = "size"
62
62
 
63
- element = entry.sizeof(PTYPEGEN)
63
+ element = entry.sizeof(PTYPEGEN).as(Carbon::Type("Carbon::UInt64"))
64
64
  size = convert_int_size(int, size, entry)
65
- total = entry.mul(element, size)
66
- entry.ret(entry.malloc(total))
65
+ total = entry.mul(element, size).as(size.type)
66
+ entry.ret(entry.malloc(total).as(PTYPE))
67
67
  end
68
68
 
69
69
  def define_free_definition(definition)
@@ -77,7 +77,7 @@ module Carbon
77
77
  def convert_int_size(int, value, entry)
78
78
  size = Int.find(sign: :unsigned, size: 64)
79
79
  name = int.name.call(size.cast, [int.name])
80
- entry.call(name, value)
80
+ entry.call(name, value).as(size.name)
81
81
  end
82
82
  end
83
83
  end
File without changes
@@ -9,6 +9,7 @@ require "carbon/tacky/value"
9
9
  require "carbon/tacky/instruction"
10
10
  require "carbon/tacky/parameter"
11
11
  require "carbon/tacky/reference"
12
+ require "carbon/tacky/typed"
12
13
 
13
14
  module Carbon
14
15
  # Tacky is a IR implementation. It is a medium-level IR, just above LLVM IR
File without changes
@@ -288,6 +288,14 @@ module Carbon
288
288
  _call(:_null, type)
289
289
  end
290
290
 
291
+ def typeof(value)
292
+ _call(:_typeof, value)
293
+ end
294
+
295
+ def mcall(mod, name, *params)
296
+ _call(:_mcall, mod, name, *params)
297
+ end
298
+
291
299
  # Creates an instruction, and returns a reference to that instruction.
292
300
  # The reference points to the instruction using the "instruction id,"
293
301
  # which is essentially the instruction's place in the block.
@@ -299,11 +307,15 @@ module Carbon
299
307
  # @param name [::String] The return value name of the instruction.
300
308
  # @return [Tacky::Reference] The reference to the new instruction.
301
309
  def _call(inst, *parameters, name: "")
310
+ # cut it off at the pass and force all parameters to instructions to
311
+ # have a type.
302
312
  id = @block.next
303
- instruction = Tacky::Instruction.new(id, inst, parameters)
313
+ typed = parameters.map { |p| Tacky::Typed.from(p) }
314
+ reference = Tacky::Reference.new(id)
315
+ instruction = Tacky::Instruction.new(id, inst, parameters, reference)
304
316
  instruction.name = name
305
317
  @block.instructions << instruction
306
- Tacky::Reference.new(id)
318
+ reference
307
319
  end
308
320
  end
309
321
  end
@@ -49,11 +49,18 @@ module Carbon
49
49
  attr_reader :functions
50
50
  def_delegator :@build, :functions
51
51
 
52
+ # Returns the function that this is being built for.
53
+ #
54
+ # @return [Tacky::Function]
55
+ attr_reader :function
56
+
52
57
  # Initialize the context.
53
58
  #
59
+ # @param function [Tacky::Function]
54
60
  # @param build [Concrete::Build]
55
61
  # @param generics [{::String => Concrete::Type}]
56
- def initialize(build, generics)
62
+ def initialize(function, build, generics)
63
+ @function = function
57
64
  @build = build
58
65
  @generics = generics
59
66
  @instructions = []
@@ -61,6 +68,10 @@ module Carbon
61
68
  @params = []
62
69
  freeze
63
70
  end
71
+
72
+ def find(name)
73
+ name.function? ? functions.fetch(name).last : types.fetch(name).last
74
+ end
64
75
  end
65
76
  end
66
77
  end
@@ -105,7 +105,7 @@ module Carbon
105
105
  # being applied to the function.
106
106
  # @return [void]
107
107
  def call(function, build, generics)
108
- context = Context.new(build, generics)
108
+ context = Context.new(self, build, generics)
109
109
  mark_function_params(context, function)
110
110
 
111
111
  @blocks.each do |block|
@@ -1,11 +1,16 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ #
4
+ require "carbon/tacky/instruction/generation"
5
+ require "carbon/tacky/instruction/typeof"
3
6
 
4
7
  module Carbon
5
8
  module Tacky
6
9
  # An instruction. This is the building block of the rest of the Tacky
7
10
  # structures. Each instruction performs some sort of action.
8
11
  class Instruction < Value
12
+ include Instruction::Generation
13
+ include Instruction::Typeof
9
14
  # Instructions that can be represented by this class that can have a
10
15
  # name parameter.
11
16
  #
@@ -40,10 +45,11 @@ module Carbon
40
45
  # @param name [::Symbol, ::String] The name of the instruction.
41
46
  # @param parameters [<Reference, Parameter, Value, ::Object>] The
42
47
  # parameters to be used with the instruction.
43
- def initialize(id, name, parameters)
48
+ def initialize(id, name, parameters, reference)
44
49
  @value = id
45
50
  @instruction = name.to_s
46
51
  @parameters = parameters
52
+ @reference = reference
47
53
  end
48
54
 
49
55
  # Builds the instruction. If the instruction is special, i.e. it starts
@@ -60,7 +66,9 @@ module Carbon
60
66
  def call(context, block)
61
67
  case @instruction
62
68
  when "_null" then generate_null(context, block)
69
+ when "_mcall" then generate_mcall(context, block)
63
70
  when "_sizeof" then generate_sizeof(context, block)
71
+ when "_typeof" then generate_typeof(context, block)
64
72
  else generate_normal(context, block)
65
73
  end
66
74
  end
@@ -112,59 +120,6 @@ module Carbon
112
120
 
113
121
  name
114
122
  end
115
-
116
- private
117
-
118
- # Generates a "normal" instruction. It maps the parameters, then sends
119
- # the instruction over to a builder for LLVM, before returning the
120
- # result of the instruction.
121
- #
122
- # @param context [Tacky::Context] The context.
123
- # @param block [::LLVM::BasicBlock] The block.
124
- # @return [::LLVM::Value] The result of the llvm instruction.
125
- def generate_normal(context, block)
126
- params = mapped_parameters(context, block)
127
- value = nil
128
-
129
- block.build { |b| value = b.public_send(@instruction, *params) }
130
- value
131
- end
132
-
133
- def generate_null(context, block)
134
- params = mapped_parameters(context, block)
135
- context.types.fetch(params.first).last.null
136
- end
137
-
138
- def generate_sizeof(context, block)
139
- params = mapped_parameters(context, block)
140
- context.types.fetch(params.first).last.size
141
- end
142
-
143
- def mapped_parameters(context, block)
144
- @parameters.map { |p| mapped_parameter(p, context, block) }
145
- end
146
-
147
- # rubocop:disable Metrics/CyclomaticComplexity
148
- def mapped_parameter(param, context, _block)
149
- case param
150
- when Concrete::Type then map_parameter_type(param, context)
151
- when Tacky::Reference then context.instructions.fetch(param.id)
152
- when Tacky::Parameter then context.params.fetch(param.value)
153
- when ::Integer then LLVM.Int(param)
154
- when ::Float then LLVM.Float(param)
155
- when ::String then param
156
- else fail ArgumentError, "Unexpected parameter #{param.class}"
157
- end
158
- end
159
- # rubocop:enable Metrics/CyclomaticComplexity
160
-
161
- def map_parameter_type(param, context)
162
- if param.function?
163
- context.functions.fetch(param)
164
- else
165
- context.types.fetch(param).last
166
- end
167
- end
168
123
  end
169
124
  end
170
125
  end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Carbon
5
+ module Tacky
6
+ class Instruction < Value
7
+ module Dependencies
8
+ def dependencies
9
+ case @instruction
10
+ when "_mcall" then dependencies_mcall
11
+ when "_ucall" then dependencies_ucall
12
+ when "_typeof" then dependencies_typeof
13
+ else dependencies_normal
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def dependencies_mcall
20
+ deps = Set.new
21
+ mod = @parameters[0]
22
+ types = @parameters[2..-1].map { }
23
+ @function = mod.call(@parameters[1])
24
+ deps << @parameters[0]
25
+ end
26
+
27
+ def dependencies_normal
28
+ @parameters.select { |p| p.is_a?(Concrete::Type) }.inject(Set.new, :<<)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end