@@ -112,17 +112,67 @@ Base.convert(::Type{T}, val::ConstantFP) where {T<:AbstractFloat} =
112
112
convert (T, API. LLVMConstRealGetDouble (val, Ref {API.LLVMBool} ()))
113
113
114
114
115
- # sequential
115
+ # sequential data
116
116
117
117
export ConstantDataSequential, ConstantDataArray, ConstantDataVector
118
118
119
119
abstract type ConstantDataSequential <: Constant end
120
120
121
+ # ConstantData can only contain primitive types (1/2/4/8 byte integers, float/half),
122
+ # as opposed to ConstantAggregate which can contain arbitrary LLVM values.
123
+ #
124
+ # however, LLVM seems to use both array types interchangeably, e.g., constructing
125
+ # a ConstArray through LLVMConstArray may return a ConstantDataArray (presumably as an
126
+ # optimization, when the data can be represented as densely packed primitive values).
127
+ # because of that, ConstantDataArray and ConstantArray need to behave the same way,
128
+ # concretely, indexing a ConstantDataArray has to return LLVM constant values...
129
+ #
130
+ # XXX : maybe we should just not expose ConstantDataArray then?
131
+ # one advantage of keeping them separate is that creating a ConstantDataArray
132
+ # is much cheaper (we should also be able to iterate much more efficiently,
133
+ # but cannot support that as explained above).
134
+
135
+ # array interface
136
+ Base. eltype (cda:: ConstantDataSequential ) = llvmeltype (cda)
137
+ Base. length (cda:: ConstantDataSequential ) = length (llvmtype (cda))
138
+ Base. size (cda:: ConstantDataSequential ) = (length (cda),)
139
+ function Base. getindex (cda:: ConstantDataSequential , idx:: Integer )
140
+ @boundscheck 1 <= idx <= length (cda) || throw (BoundsError (cda, idx))
141
+ Value (API. LLVMGetElementAsConstant (cda, idx- 1 ))
142
+ end
143
+ function Base. collect (cda:: ConstantDataSequential )
144
+ constants = Array {Value} (undef, length (cda))
145
+ for i in 1 : length (cda)
146
+ @inbounds constants[i] = cda[i]
147
+ end
148
+ return constants
149
+ end
150
+
121
151
@checked struct ConstantDataArray <: ConstantDataSequential
122
152
ref:: API.LLVMValueRef
123
153
end
124
154
register (ConstantDataArray, API. LLVMConstantDataArrayValueKind)
125
155
156
+ function ConstantDataArray (typ:: LLVMType , data:: Array{T} ) where {T <: Union{Integer, AbstractFloat} }
157
+ # TODO : can we look up the primitive size of the LLVM type?
158
+ # use that to assert it matches the Julia element type.
159
+ return ConstantDataArray (API. LLVMConstDataArray (typ, data, length (data)))
160
+ end
161
+
162
+ # shorthands with arrays of plain Julia data
163
+ # FIXME : duplicates the ConstantInt/ConstantFP conversion rules
164
+ # XXX : X[X(...)] instead of X.(...) because of empty-container inference
165
+ ConstantDataArray (data:: AbstractVector{T} ; ctx:: Context ) where {T<: Integer } =
166
+ ConstantDataArray (IntType (sizeof (T)* 8 ; ctx), data)
167
+ ConstantDataArray (data:: AbstractVector{Core.Bool} ; ctx:: Context ) =
168
+ ConstantDataArray (Int1Type (ctx), data)
169
+ ConstantDataArray (data:: AbstractVector{Float16} ; ctx:: Context ) =
170
+ ConstantDataArray (HalfType (ctx), data)
171
+ ConstantDataArray (data:: AbstractVector{Float32} ; ctx:: Context ) =
172
+ ConstantDataArray (FloatType (ctx), data)
173
+ ConstantDataArray (data:: AbstractVector{Float64} ; ctx:: Context ) =
174
+ ConstantDataArray (DoubleType (ctx), data)
175
+
126
176
@checked struct ConstantDataVector <: ConstantDataSequential
127
177
ref:: API.LLVMValueRef
128
178
end
@@ -162,16 +212,14 @@ export ConstantArray
162
212
ref:: API.LLVMValueRef
163
213
end
164
214
register (ConstantArray, API. LLVMConstantArrayValueKind)
165
- register (ConstantArray, API. LLVMConstantDataArrayValueKind)
166
-
167
- ConstantArrayOrAggregateZero (value) = Value (value):: Union{ConstantArray,ConstantAggregateZero}
168
215
169
216
# generic constructor taking an array of constants
170
217
function ConstantArray (typ:: LLVMType , data:: AbstractArray{T,N} = T[]) where {T<: Constant ,N}
171
218
@assert all (x-> x== typ, llvmtype .(data))
172
219
173
220
if N == 1
174
- return ConstantArrayOrAggregateZero (API. LLVMConstArray (typ, Array (data), length (data)))
221
+ # XXX : this can return a ConstDataArray (presumably as an optimization?)
222
+ return Value (API. LLVMConstArray (typ, Array (data), length (data)))
175
223
end
176
224
177
225
ca_vec = map (x-> ConstantArray (typ, x), eachslice (data, dims= 1 ))
@@ -183,15 +231,15 @@ end
183
231
# shorthands with arrays of plain Julia data
184
232
# FIXME : duplicates the ConstantInt/ConstantFP conversion rules
185
233
# XXX : X[X(...)] instead of X.(...) because of empty-container inference
186
- ConstantArray (data:: AbstractArray{T,N } ; ctx:: Context ) where {T<: Integer ,N } =
234
+ ConstantArray (data:: AbstractArray{T} ; ctx:: Context ) where {T<: Integer } =
187
235
ConstantArray (IntType (sizeof (T)* 8 ; ctx), ConstantInt[ConstantInt (x; ctx) for x in data])
188
- ConstantArray (data:: AbstractArray{Core.Bool,N } ; ctx:: Context ) where {N} =
236
+ ConstantArray (data:: AbstractArray{Core.Bool} ; ctx:: Context ) =
189
237
ConstantArray (Int1Type (ctx), ConstantInt[ConstantInt (x; ctx) for x in data])
190
- ConstantArray (data:: AbstractArray{Float16,N } ; ctx:: Context ) where {N} =
238
+ ConstantArray (data:: AbstractArray{Float16} ; ctx:: Context ) =
191
239
ConstantArray (HalfType (ctx), ConstantFP[ConstantFP (x; ctx) for x in data])
192
- ConstantArray (data:: AbstractArray{Float32,N } ; ctx:: Context ) where {N} =
240
+ ConstantArray (data:: AbstractArray{Float32} ; ctx:: Context ) =
193
241
ConstantArray (FloatType (ctx), ConstantFP[ConstantFP (x; ctx) for x in data])
194
- ConstantArray (data:: AbstractArray{Float64,N } ; ctx:: Context ) where {N} =
242
+ ConstantArray (data:: AbstractArray{Float64} ; ctx:: Context ) =
195
243
ConstantArray (DoubleType (ctx), ConstantFP[ConstantFP (x; ctx) for x in data])
196
244
197
245
# convert back to known array types
@@ -226,7 +274,9 @@ function Base.getindex(ca::ConstantArray, idx::Integer...)
226
274
I = CartesianIndices (size (ca))[idx... ]
227
275
for i in Tuple (I)
228
276
if isempty (operands (ca))
229
- ca = LLVM. Value (API. LLVMGetElementAsConstant (ca, i- 1 ))
277
+ # XXX : is this valid? LLVMGetElementAsConstant is meant to be used with
278
+ # Constant*Data*Arrays, not ConstantArrays
279
+ ca = Value (API. LLVMGetElementAsConstant (ca, i- 1 ))
230
280
else
231
281
ca = (Base. @_propagate_inbounds_meta ; operands (ca)[i])
232
282
end
0 commit comments