@@ -112,17 +112,67 @@ Base.convert(::Type{T}, val::ConstantFP) where {T<:AbstractFloat} =
112112 convert (T, API. LLVMConstRealGetDouble (val, Ref {API.LLVMBool} ()))
113113
114114
115- # sequential
115+ # sequential data
116116
117117export ConstantDataSequential, ConstantDataArray, ConstantDataVector
118118
119119abstract type ConstantDataSequential <: Constant end
120120
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+
121151@checked struct ConstantDataArray <: ConstantDataSequential
122152 ref:: API.LLVMValueRef
123153end
124154register (ConstantDataArray, API. LLVMConstantDataArrayValueKind)
125155
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+
126176@checked struct ConstantDataVector <: ConstantDataSequential
127177 ref:: API.LLVMValueRef
128178end
@@ -162,16 +212,14 @@ export ConstantArray
162212 ref:: API.LLVMValueRef
163213end
164214register (ConstantArray, API. LLVMConstantArrayValueKind)
165- register (ConstantArray, API. LLVMConstantDataArrayValueKind)
166-
167- ConstantArrayOrAggregateZero (value) = Value (value):: Union{ConstantArray,ConstantAggregateZero}
168215
169216# generic constructor taking an array of constants
170217function ConstantArray (typ:: LLVMType , data:: AbstractArray{T,N} = T[]) where {T<: Constant ,N}
171218 @assert all (x-> x== typ, llvmtype .(data))
172219
173220 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)))
175223 end
176224
177225 ca_vec = map (x-> ConstantArray (typ, x), eachslice (data, dims= 1 ))
@@ -183,15 +231,15 @@ end
183231# shorthands with arrays of plain Julia data
184232# FIXME : duplicates the ConstantInt/ConstantFP conversion rules
185233# 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 } =
187235 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 ) =
189237 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 ) =
191239 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 ) =
193241 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 ) =
195243 ConstantArray (DoubleType (ctx), ConstantFP[ConstantFP (x; ctx) for x in data])
196244
197245# convert back to known array types
@@ -226,7 +274,9 @@ function Base.getindex(ca::ConstantArray, idx::Integer...)
226274 I = CartesianIndices (size (ca))[idx... ]
227275 for i in Tuple (I)
228276 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 ))
230280 else
231281 ca = (Base. @_propagate_inbounds_meta ; operands (ca)[i])
232282 end
0 commit comments