diff --git a/Manifest.toml b/Manifest.toml index a6a0199d..33d94b16 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -34,9 +34,9 @@ version = "1.4.1" [[LLVMExtra_jll]] deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] -git-tree-sha1 = "e46e3a40daddcbe851f86db0ec4a4a3d4badf800" +git-tree-sha1 = "070e4b5b65827f82c16ae0916376cb47377aa1b5" uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab" -version = "0.0.19+0" +version = "0.0.18+0" [[LazyArtifacts]] deps = ["Artifacts", "Pkg"] diff --git a/Project.toml b/Project.toml index 83340148..566fd274 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "LLVM" uuid = "929cbde3-209d-540e-8aea-75f648917ca0" -version = "4.17.0" +version = "4.17.1" [deps] CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82" @@ -11,5 +11,5 @@ Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" [compat] CEnum = "0.2, 0.3, 0.4" -LLVMExtra_jll = "=0.0.19" +LLVMExtra_jll = "=0.0.18" julia = "1.6" diff --git a/deps/LLVMExtra/include/LLVMExtra.h b/deps/LLVMExtra/include/LLVMExtra.h index 3a2fd60d..a74e700f 100644 --- a/deps/LLVMExtra/include/LLVMExtra.h +++ b/deps/LLVMExtra/include/LLVMExtra.h @@ -162,8 +162,5 @@ void LLVMReplaceMDNodeOperandWith(LLVMMetadataRef MD, unsigned I, LLVMMetadataRe LLVMBool LLVMContextSupportsTypedPointers(LLVMContextRef C); #endif -// constant data -LLVMValueRef LLVMConstDataArray(LLVMTypeRef ElementTy, const void *Data, unsigned NumElements); - LLVM_C_EXTERN_C_END #endif diff --git a/deps/LLVMExtra/lib/llvm-api.cpp b/deps/LLVMExtra/lib/llvm-api.cpp index 6aeed0ae..cfea2a95 100644 --- a/deps/LLVMExtra/lib/llvm-api.cpp +++ b/deps/LLVMExtra/lib/llvm-api.cpp @@ -556,8 +556,3 @@ LLVMBool LLVMContextSupportsTypedPointers(LLVMContextRef C) { return unwrap(C)->supportsTypedPointers(); } #endif - -LLVMValueRef LLVMConstDataArray(LLVMTypeRef ElementTy, const void *Data, unsigned NumElements) { - StringRef S((const char *)Data, NumElements * unwrap(ElementTy)->getPrimitiveSizeInBits() / 8); - return wrap(ConstantDataArray::getRaw(S, NumElements, unwrap(ElementTy))); -} diff --git a/lib/libLLVM_extra.jl b/lib/libLLVM_extra.jl index 1329dbbb..5acb9a48 100644 --- a/lib/libLLVM_extra.jl +++ b/lib/libLLVM_extra.jl @@ -416,7 +416,3 @@ function LLVMContextSupportsTypedPointers(Ctx) ccall((:LLVMContextSupportsTypedPointers, libLLVMExtra), LLVMBool, (LLVMContextRef,), Ctx) end end - -function LLVMConstDataArray(ElementTy, Data, NumElements) - ccall((:LLVMConstDataArray, libLLVMExtra), LLVMValueRef, (LLVMTypeRef, Ptr{Cvoid}, Cuint), ElementTy, Data, NumElements) -end diff --git a/src/core/module.jl b/src/core/module.jl index f4f764fa..950389a4 100644 --- a/src/core/module.jl +++ b/src/core/module.jl @@ -267,30 +267,3 @@ function Base.setindex!(iter::ModuleFlagDict, val::Metadata, (name, behavior)::Tuple{String, API.LLVMModuleFlagBehavior}) API.LLVMAddModuleFlag(iter.mod, behavior, name, length(name), val) end - - -## sdk version - -export sdk_version, sdk_version! - -function sdk_version!(mod::Module, version::VersionNumber) - entries = Int32[version.major] - if version.minor != 0 || version.patch != 0 - push!(entries, version.minor) - if version.patch != 0 - push!(entries, version.patch) - end - # cannot represent prerelease or build metadata - end - md = Metadata(ConstantDataArray(entries; ctx=context(mod))) - - flags(mod)["SDK Version", LLVM.API.LLVMModuleFlagBehaviorWarning] = md -end - -function sdk_version(mod::Module) - haskey(flags(mod), "SDK Version") || return nothing - md = flags(mod)["SDK Version"] - c = Value(md; ctx=context(mod)) - entries = collect(c) - VersionNumber(map(val->convert(Int, val), entries)...) -end diff --git a/src/core/type.jl b/src/core/type.jl index 78f92208..828d8329 100644 --- a/src/core/type.jl +++ b/src/core/type.jl @@ -163,7 +163,7 @@ function ArrayType(eltyp::LLVMType, count) return ArrayType(API.LLVMArrayType(eltyp, count)) end -Base.length(arrtyp::ArrayType) = Int(API.LLVMGetArrayLength(arrtyp)) +Base.length(arrtyp::ArrayType) = API.LLVMGetArrayLength(arrtyp) Base.isempty(@nospecialize(T::ArrayType)) = length(T) == 0 || isempty(eltype(T)) diff --git a/src/core/value/constant.jl b/src/core/value/constant.jl index 589811a2..615cc6fb 100644 --- a/src/core/value/constant.jl +++ b/src/core/value/constant.jl @@ -112,67 +112,17 @@ Base.convert(::Type{T}, val::ConstantFP) where {T<:AbstractFloat} = convert(T, API.LLVMConstRealGetDouble(val, Ref{API.LLVMBool}())) -# sequential data +# sequential export ConstantDataSequential, ConstantDataArray, ConstantDataVector abstract type ConstantDataSequential <: Constant end -# ConstantData can only contain primitive types (1/2/4/8 byte integers, float/half), -# as opposed to ConstantAggregate which can contain arbitrary LLVM values. -# -# however, LLVM seems to use both array types interchangeably, e.g., constructing -# a ConstArray through LLVMConstArray may return a ConstantDataArray (presumably as an -# optimization, when the data can be represented as densely packed primitive values). -# because of that, ConstantDataArray and ConstantArray need to behave the same way, -# concretely, indexing a ConstantDataArray has to return LLVM constant values... -# -# XXX: maybe we should just not expose ConstantDataArray then? -# one advantage of keeping them separate is that creating a ConstantDataArray -# is much cheaper (we should also be able to iterate much more efficiently, -# but cannot support that as explained above). - -# array interface -Base.eltype(cda::ConstantDataSequential) = llvmeltype(cda) -Base.length(cda::ConstantDataSequential) = length(llvmtype(cda)) -Base.size(cda::ConstantDataSequential) = (length(cda),) -function Base.getindex(cda::ConstantDataSequential, idx::Integer) - @boundscheck 1 <= idx <= length(cda) || throw(BoundsError(cda, idx)) - Value(API.LLVMGetElementAsConstant(cda, idx-1)) -end -function Base.collect(cda::ConstantDataSequential) - constants = Array{Value}(undef, length(cda)) - for i in 1:length(cda) - @inbounds constants[i] = cda[i] - end - return constants -end - @checked struct ConstantDataArray <: ConstantDataSequential ref::API.LLVMValueRef end register(ConstantDataArray, API.LLVMConstantDataArrayValueKind) -function ConstantDataArray(typ::LLVMType, data::Array{T}) where {T <: Union{Integer, AbstractFloat}} - # TODO: can we look up the primitive size of the LLVM type? - # use that to assert it matches the Julia element type. - return ConstantDataArray(API.LLVMConstDataArray(typ, data, length(data))) -end - -# shorthands with arrays of plain Julia data -# FIXME: duplicates the ConstantInt/ConstantFP conversion rules -# XXX: X[X(...)] instead of X.(...) because of empty-container inference -ConstantDataArray(data::AbstractVector{T}; ctx::Context) where {T<:Integer} = - ConstantDataArray(IntType(sizeof(T)*8; ctx), data) -ConstantDataArray(data::AbstractVector{Core.Bool}; ctx::Context) = - ConstantDataArray(Int1Type(ctx), data) -ConstantDataArray(data::AbstractVector{Float16}; ctx::Context) = - ConstantDataArray(HalfType(ctx), data) -ConstantDataArray(data::AbstractVector{Float32}; ctx::Context) = - ConstantDataArray(FloatType(ctx), data) -ConstantDataArray(data::AbstractVector{Float64}; ctx::Context) = - ConstantDataArray(DoubleType(ctx), data) - @checked struct ConstantDataVector <: ConstantDataSequential ref::API.LLVMValueRef end @@ -212,14 +162,16 @@ export ConstantArray ref::API.LLVMValueRef end register(ConstantArray, API.LLVMConstantArrayValueKind) +register(ConstantArray, API.LLVMConstantDataArrayValueKind) + +ConstantArrayOrAggregateZero(value) = Value(value)::Union{ConstantArray,ConstantAggregateZero} # generic constructor taking an array of constants function ConstantArray(typ::LLVMType, data::AbstractArray{T,N}=T[]) where {T<:Constant,N} @assert all(x->x==typ, llvmtype.(data)) if N == 1 - # XXX: this can return a ConstDataArray (presumably as an optimization?) - return Value(API.LLVMConstArray(typ, Array(data), length(data))) + return ConstantArrayOrAggregateZero(API.LLVMConstArray(typ, Array(data), length(data))) end ca_vec = map(x->ConstantArray(typ, x), eachslice(data, dims=1)) @@ -231,15 +183,15 @@ end # shorthands with arrays of plain Julia data # FIXME: duplicates the ConstantInt/ConstantFP conversion rules # XXX: X[X(...)] instead of X.(...) because of empty-container inference -ConstantArray(data::AbstractArray{T}; ctx::Context) where {T<:Integer} = +ConstantArray(data::AbstractArray{T,N}; ctx::Context) where {T<:Integer,N} = ConstantArray(IntType(sizeof(T)*8; ctx), ConstantInt[ConstantInt(x; ctx) for x in data]) -ConstantArray(data::AbstractArray{Core.Bool}; ctx::Context) = +ConstantArray(data::AbstractArray{Core.Bool,N}; ctx::Context) where {N} = ConstantArray(Int1Type(ctx), ConstantInt[ConstantInt(x; ctx) for x in data]) -ConstantArray(data::AbstractArray{Float16}; ctx::Context) = +ConstantArray(data::AbstractArray{Float16,N}; ctx::Context) where {N} = ConstantArray(HalfType(ctx), ConstantFP[ConstantFP(x; ctx) for x in data]) -ConstantArray(data::AbstractArray{Float32}; ctx::Context) = +ConstantArray(data::AbstractArray{Float32,N}; ctx::Context) where {N} = ConstantArray(FloatType(ctx), ConstantFP[ConstantFP(x; ctx) for x in data]) -ConstantArray(data::AbstractArray{Float64}; ctx::Context) = +ConstantArray(data::AbstractArray{Float64,N}; ctx::Context) where {N} = ConstantArray(DoubleType(ctx), ConstantFP[ConstantFP(x; ctx) for x in data]) # convert back to known array types @@ -274,9 +226,7 @@ function Base.getindex(ca::ConstantArray, idx::Integer...) I = CartesianIndices(size(ca))[idx...] for i in Tuple(I) if isempty(operands(ca)) - # XXX: is this valid? LLVMGetElementAsConstant is meant to be used with - # Constant*Data*Arrays, not ConstantArrays - ca = Value(API.LLVMGetElementAsConstant(ca, i-1)) + ca = LLVM.Value(API.LLVMGetElementAsConstant(ca, i-1)) else ca = (Base.@_propagate_inbounds_meta; operands(ca)[i]) end diff --git a/test/core.jl b/test/core.jl index eb07a663..f6a32e50 100644 --- a/test/core.jl +++ b/test/core.jl @@ -419,23 +419,29 @@ end end - @testset "array aggregate constants" begin + @testset "array constants" begin # from Julia values let - vec = Int128[1,2,3,4] + vec = Int32[1,2,3,4] ca = ConstantArray(vec; ctx) - @test ca isa ConstantArray @test size(vec) == size(ca) @test length(vec) == length(ca) @test ca[1] == ConstantInt(vec[1]; ctx) @test collect(ca) == ConstantInt.(vec; ctx) end + let + vec = Float32[1.1f0,2.2f0,3.3f0,4.4f0] + ca = ConstantArray(vec; ctx) + @test size(vec) == size(ca) + @test length(vec) == length(ca) + @test ca[1] == ConstantFP(vec[1]; ctx) + @test collect(ca) == ConstantFP.(vec; ctx) + end let # tests for ConstantAggregateZero, constructed indirectly. # should behave similarly to ConstantArray since it can get returned there. ca = ConstantArray(Int[]; ctx) - @test ca isa ConstantAggregateZero @test size(ca) == (0,) @test length(ca) == 0 @test isempty(collect(ca)) @@ -452,7 +458,7 @@ end end - @testset "struct aggregate constants" begin + @testset "struct constants" begin # from Julia values let @@ -507,36 +513,6 @@ end end end - - - @testset "array data constants" begin - - let - vec = Int32[1,2,3,4] - eltyp = LLVM.Int32Type(ctx) - cda = ConstantDataArray(eltyp, vec) - @test cda isa ConstantDataArray - @test llvmtype(cda) == LLVM.ArrayType(eltyp, 4) - @test collect(cda) == ConstantInt.(vec; ctx) - end - - # from Julia values - for T in [Int8, Int16, Int32, Int64] - vec = T[1,2,3,4] - cda = ConstantDataArray(vec; ctx) - @test cda isa ConstantDataArray - @test size(vec) == size(cda) - @test collect(cda) == ConstantInt.(vec; ctx) - end - for T in [Float32, Float64] - vec = T[1,2,3,4] - cda = ConstantDataArray(vec; ctx) - @test cda isa ConstantDataArray - @test size(vec) == size(cda) - @test collect(cda) == ConstantFP.(vec; ctx) - end - - end end # constant expressions @@ -1015,10 +991,6 @@ end @test mod_flags["foobar"] == md @test_throws KeyError mod_flags["foobaz"] - - @test sdk_version(mod) === nothing - sdk_version!(mod, v"1.2.3") - @test sdk_version(mod) == v"1.2.3" end # metadata iteration