diff --git a/deps/LLVMExtra/include/LLVMExtra.h b/deps/LLVMExtra/include/LLVMExtra.h index c7ec78be..06833a3a 100644 --- a/deps/LLVMExtra/include/LLVMExtra.h +++ b/deps/LLVMExtra/include/LLVMExtra.h @@ -84,6 +84,14 @@ void LLVMDestroyConstant(LLVMValueRef Const); LLVMTypeRef LLVMGetFunctionType(LLVMValueRef Fn); LLVMTypeRef LLVMGetGlobalValueType(LLVMValueRef Fn); +// Attribute type detection (ConstantRange/ConstantRangeList kinds not exposed in C API) +#if LLVM_VERSION_MAJOR >= 19 +LLVMBool LLVMIsConstantRangeAttribute(LLVMAttributeRef A); +#endif +#if LLVM_VERSION_MAJOR >= 20 +LLVMBool LLVMIsConstantRangeListAttribute(LLVMAttributeRef A); +#endif + // Bug fixes #if LLVM_VERSION_MAJOR < 20 // llvm/llvm-project#105521 void LLVMSetInitializer2(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal); diff --git a/deps/LLVMExtra/lib/Core.cpp b/deps/LLVMExtra/lib/Core.cpp index a11222d4..c8613f26 100644 --- a/deps/LLVMExtra/lib/Core.cpp +++ b/deps/LLVMExtra/lib/Core.cpp @@ -295,6 +295,27 @@ LLVMTypeRef LLVMGetGlobalValueType(LLVMValueRef GV) { } +// +// Attribute type detection +// + +#if LLVM_VERSION_MAJOR >= 19 + +LLVMBool LLVMIsConstantRangeAttribute(LLVMAttributeRef A) { + return unwrap(A).isConstantRangeAttribute(); +} + +#endif + +#if LLVM_VERSION_MAJOR >= 20 + +LLVMBool LLVMIsConstantRangeListAttribute(LLVMAttributeRef A) { + return unwrap(A).isConstantRangeListAttribute(); +} + +#endif + + // // Bug fixes // diff --git a/lib/17/libLLVM_extra.jl b/lib/17/libLLVM_extra.jl index b0361b91..f6876203 100644 --- a/lib/17/libLLVM_extra.jl +++ b/lib/17/libLLVM_extra.jl @@ -110,6 +110,10 @@ function LLVMGetGlobalValueType(Fn) ccall((:LLVMGetGlobalValueType, libLLVMExtra), LLVMTypeRef, (LLVMValueRef,), Fn) end +function LLVMIsConstantRangeAttribute(A) + ccall((:LLVMIsConstantRangeAttribute, libLLVMExtra), LLVMBool, (LLVMAttributeRef,), A) +end + function LLVMSetInitializer2(GlobalVar, ConstantVal) ccall((:LLVMSetInitializer2, libLLVMExtra), Cvoid, (LLVMValueRef, LLVMValueRef), GlobalVar, ConstantVal) end diff --git a/lib/18/libLLVM_extra.jl b/lib/18/libLLVM_extra.jl index 57a78abf..be9d885a 100644 --- a/lib/18/libLLVM_extra.jl +++ b/lib/18/libLLVM_extra.jl @@ -110,6 +110,10 @@ function LLVMGetGlobalValueType(Fn) ccall((:LLVMGetGlobalValueType, libLLVMExtra), LLVMTypeRef, (LLVMValueRef,), Fn) end +function LLVMIsConstantRangeAttribute(A) + ccall((:LLVMIsConstantRangeAttribute, libLLVMExtra), LLVMBool, (LLVMAttributeRef,), A) +end + function LLVMSetInitializer2(GlobalVar, ConstantVal) ccall((:LLVMSetInitializer2, libLLVMExtra), Cvoid, (LLVMValueRef, LLVMValueRef), GlobalVar, ConstantVal) end diff --git a/lib/19/libLLVM_extra.jl b/lib/19/libLLVM_extra.jl index 57a78abf..be9d885a 100644 --- a/lib/19/libLLVM_extra.jl +++ b/lib/19/libLLVM_extra.jl @@ -110,6 +110,10 @@ function LLVMGetGlobalValueType(Fn) ccall((:LLVMGetGlobalValueType, libLLVMExtra), LLVMTypeRef, (LLVMValueRef,), Fn) end +function LLVMIsConstantRangeAttribute(A) + ccall((:LLVMIsConstantRangeAttribute, libLLVMExtra), LLVMBool, (LLVMAttributeRef,), A) +end + function LLVMSetInitializer2(GlobalVar, ConstantVal) ccall((:LLVMSetInitializer2, libLLVMExtra), Cvoid, (LLVMValueRef, LLVMValueRef), GlobalVar, ConstantVal) end diff --git a/lib/20/libLLVM_extra.jl b/lib/20/libLLVM_extra.jl index 83c6a6ac..d072fa3d 100644 --- a/lib/20/libLLVM_extra.jl +++ b/lib/20/libLLVM_extra.jl @@ -110,6 +110,14 @@ function LLVMGetGlobalValueType(Fn) ccall((:LLVMGetGlobalValueType, libLLVMExtra), LLVMTypeRef, (LLVMValueRef,), Fn) end +function LLVMIsConstantRangeAttribute(A) + ccall((:LLVMIsConstantRangeAttribute, libLLVMExtra), LLVMBool, (LLVMAttributeRef,), A) +end + +function LLVMIsConstantRangeListAttribute(A) + ccall((:LLVMIsConstantRangeListAttribute, libLLVMExtra), LLVMBool, (LLVMAttributeRef,), A) +end + function LLVMGetMDString2(MD, Length) ccall((:LLVMGetMDString2, libLLVMExtra), Cstring, (LLVMMetadataRef, Ptr{Cuint}), MD, Length) end diff --git a/lib/21/libLLVM_extra.jl b/lib/21/libLLVM_extra.jl index 62dfdda8..427e7576 100644 --- a/lib/21/libLLVM_extra.jl +++ b/lib/21/libLLVM_extra.jl @@ -110,6 +110,14 @@ function LLVMGetGlobalValueType(Fn) ccall((:LLVMGetGlobalValueType, libLLVMExtra), LLVMTypeRef, (LLVMValueRef,), Fn) end +function LLVMIsConstantRangeAttribute(A) + ccall((:LLVMIsConstantRangeAttribute, libLLVMExtra), LLVMBool, (LLVMAttributeRef,), A) +end + +function LLVMIsConstantRangeListAttribute(A) + ccall((:LLVMIsConstantRangeListAttribute, libLLVMExtra), LLVMBool, (LLVMAttributeRef,), A) +end + function LLVMGetMDString2(MD, Length) ccall((:LLVMGetMDString2, libLLVMExtra), Cstring, (LLVMMetadataRef, Ptr{Cuint}), MD, Length) end diff --git a/src/core/attributes.jl b/src/core/attributes.jl index abc20087..8dfbd205 100644 --- a/src/core/attributes.jl +++ b/src/core/attributes.jl @@ -3,6 +3,7 @@ export Attribute, EnumAttribute, StringAttribute, TypeAttribute, + ConstantRangeAttribute, ConstantRangeListAttribute, kind, value abstract type Attribute end @@ -21,6 +22,16 @@ end ref::API.LLVMAttributeRef end +# ConstantRange attribute kind (e.g. `range`, introduced in LLVM 17). +@checked struct ConstantRangeAttribute <: Attribute + ref::API.LLVMAttributeRef +end + +# ConstantRangeList attribute kind (e.g. `initializes`, introduced in LLVM 20). +@checked struct ConstantRangeListAttribute <: Attribute + ref::API.LLVMAttributeRef +end + # TODO: make the identify mechanism flexible enough to cover cases like this one, # and not only Value and Type @@ -33,6 +44,12 @@ function Attribute(ref::API.LLVMAttributeRef) elseif Bool(API.LLVMIsTypeAttribute(ref)) return TypeAttribute(ref) else + @static if version() >= v"20" + Bool(API.LLVMIsConstantRangeAttribute(ref)) && return ConstantRangeAttribute(ref) + Bool(API.LLVMIsConstantRangeListAttribute(ref)) && return ConstantRangeListAttribute(ref) + elseif version() >= v"19" + Bool(API.LLVMIsConstantRangeAttribute(ref)) && return ConstantRangeAttribute(ref) + end error("unknown attribute kind") end end @@ -87,3 +104,21 @@ kind(attr::TypeAttribute) = API.LLVMGetEnumAttributeKind(attr) function value(attr::TypeAttribute) return LLVMType(API.LLVMGetTypeAttributeValue(attr)) end + +## constant range attribute + +if version() >= v"19" + function ConstantRangeAttribute(kind::String, nbits::Integer, + lower::Vector{UInt64}, upper::Vector{UInt64}) + enum_kind = API.LLVMGetEnumAttributeKindForName(kind, Csize_t(length(kind))) + return ConstantRangeAttribute( + API.LLVMCreateConstantRangeAttribute(context(), enum_kind, Cuint(nbits), + lower, upper)) + end +end + +kind(attr::ConstantRangeAttribute) = API.LLVMGetEnumAttributeKind(attr) + +## constant range list attribute + +kind(attr::ConstantRangeListAttribute) = API.LLVMGetEnumAttributeKind(attr) diff --git a/src/core/function.jl b/src/core/function.jl index 943e169d..2c5d51e6 100644 --- a/src/core/function.jl +++ b/src/core/function.jl @@ -166,6 +166,12 @@ Base.delete!(iter::FunctionAttrSet, attr::EnumAttribute) = Base.delete!(iter::FunctionAttrSet, attr::TypeAttribute) = API.LLVMRemoveEnumAttributeAtIndex(iter.f, iter.idx, kind(attr)) +Base.delete!(iter::FunctionAttrSet, attr::ConstantRangeAttribute) = + API.LLVMRemoveEnumAttributeAtIndex(iter.f, iter.idx, kind(attr)) + +Base.delete!(iter::FunctionAttrSet, attr::ConstantRangeListAttribute) = + API.LLVMRemoveEnumAttributeAtIndex(iter.f, iter.idx, kind(attr)) + function Base.delete!(iter::FunctionAttrSet, attr::StringAttribute) k = kind(attr) API.LLVMRemoveStringAttributeAtIndex(iter.f, iter.idx, k, length(k)) diff --git a/src/core/instructions.jl b/src/core/instructions.jl index 1a58001e..88310389 100644 --- a/src/core/instructions.jl +++ b/src/core/instructions.jl @@ -400,6 +400,12 @@ Base.delete!(iter::CallSiteAttrSet, attr::LLVM.EnumAttribute) = Base.delete!(iter::CallSiteAttrSet, attr::LLVM.TypeAttribute) = LLVM.API.LLVMRemoveCallSiteEnumAttribute(iter.instr, iter.idx, kind(attr)) +Base.delete!(iter::CallSiteAttrSet, attr::LLVM.ConstantRangeAttribute) = + LLVM.API.LLVMRemoveCallSiteEnumAttribute(iter.instr, iter.idx, kind(attr)) + +Base.delete!(iter::CallSiteAttrSet, attr::LLVM.ConstantRangeListAttribute) = + LLVM.API.LLVMRemoveCallSiteEnumAttribute(iter.instr, iter.idx, kind(attr)) + function Base.delete!(iter::CallSiteAttrSet, attr::LLVM.StringAttribute) k = kind(attr) return LLVM.API.LLVMRemoveCallSiteStringAttribute(iter.instr, iter.idx, k, length(k)) diff --git a/test/core.jl b/test/core.jl index b45625ab..ecedb696 100644 --- a/test/core.jl +++ b/test/core.jl @@ -1404,6 +1404,17 @@ end delete!(instr_attrs, instr_attr) @test length(instr_attrs) == 0 end + + if LLVM.version() >= v"19" + let attr = ConstantRangeAttribute("range", 32, UInt64[0], UInt64[100]) + @test attr isa ConstantRangeAttribute + @test kind(attr) != 0 + push!(return_attributes(fn), attr) + collected = collect(return_attributes(fn)) + @test any(a -> a isa ConstantRangeAttribute, collected) + delete!(return_attributes(fn), attr) + end + end end for i in 1:length(parameters(fn))