Skip to content

Commit 2eca72f

Browse files
authored
Merge pull request #193 from maleadt/tb/intrinsics
Wrap intrinsics API.
2 parents c5c0354 + e440c07 commit 2eca72f

File tree

5 files changed

+100
-6
lines changed

5 files changed

+100
-6
lines changed

src/core/function.jl

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export unsafe_delete!,
22
personality, personality!,
33
callconv, callconv!,
4-
gc, gc!, intrinsic_id,
4+
gc, gc!,
55
entry
66

77
# forward declaration of Function in src/core/basicblock.jl
@@ -19,8 +19,6 @@ end
1919
personality!(f::Function, persfn::Union{Nothing,Function}) =
2020
API.LLVMSetPersonalityFn(ref(f), persfn===nothing ? C_NULL : ref(persfn))
2121

22-
intrinsic_id(f::Function) = API.LLVMGetIntrinsicID(ref(f))
23-
2422
callconv(f::Function) = API.LLVMGetFunctionCallConv(ref(f))
2523
callconv!(f::Function, cc) = API.LLVMSetFunctionCallConv(ref(f), cc)
2624

@@ -142,3 +140,66 @@ function Base.collect(iter::FunctionBlockSet)
142140
API.LLVMGetBasicBlocks(ref(iter.f), elems)
143141
return BasicBlock[BasicBlock(elem) for elem in elems]
144142
end
143+
144+
# intrinsics
145+
146+
export isintrinsic, Intrinsic, isoverloaded, declaration
147+
148+
isintrinsic(f::Function) = API.LLVMGetIntrinsicID(ref(f)) != 0
149+
150+
struct Intrinsic
151+
id::UInt32
152+
153+
function Intrinsic(f::Function)
154+
id = API.LLVMGetIntrinsicID(ref(f))
155+
id == 0 && throw(ArgumentError("Function is not an intrinsic"))
156+
new(id)
157+
end
158+
159+
function Intrinsic(name::String)
160+
@assert version() >= v"9"
161+
new(API.LLVMLookupIntrinsicID(name, length(name)))
162+
end
163+
end
164+
165+
Base.convert(::Type{UInt32}, intr::Intrinsic) = intr.id
166+
167+
function name(intr::Intrinsic)
168+
@assert version() >= v"8"
169+
len = Ref{Csize_t}()
170+
str = API.LLVMIntrinsicGetName(intr, len)
171+
unsafe_string(convert(Ptr{Cchar}, str), len[])
172+
end
173+
174+
function name(intr::Intrinsic, params::Vector{<:LLVMType})
175+
@assert version() >= v"8"
176+
len = Ref{Csize_t}()
177+
str = API.LLVMIntrinsicCopyOverloadedName(intr, ref.(params), length(params), len)
178+
unsafe_message(convert(Ptr{Cchar}, str), len[])
179+
end
180+
181+
function isoverloaded(intr::Intrinsic)
182+
@assert version() >= v"8"
183+
convert(Core.Bool, API.LLVMIntrinsicIsOverloaded(intr))
184+
end
185+
186+
function Function(mod::Module, intr::Intrinsic, params::Vector{<:LLVMType}=LLVMType[])
187+
@assert version() >= v"8"
188+
Value(API.LLVMGetIntrinsicDeclaration(ref(mod), intr, ref.(params), length(params)))
189+
end
190+
191+
function FunctionType(intr::Intrinsic, params::Vector{<:LLVMType}=LLVMType[];
192+
ctx::Context=GlobalContext())
193+
@assert version() >= v"8"
194+
LLVMType(API.LLVMIntrinsicGetType(ref(ctx), intr, ref.(params), length(params)))
195+
end
196+
197+
function Base.show(io::IO, intr::Intrinsic)
198+
print(io, "Intrinsic($(intr.id))")
199+
if version() >= v"8"
200+
print(io, ": \"$(name(intr))\"")
201+
if isoverloaded(intr)
202+
print(io, " (overloaded)")
203+
end
204+
end
205+
end

src/deprecated.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ import Base: haskey, getindex, get
1111
@deprecate haskey(::TargetIterator, name::String) Target(;name=name) !== nothing
1212
@deprecate getindex(iter::TargetIterator, name::String) Target(;name=name)
1313
@deprecate get(::TargetIterator, name::String, default) try Target(;name=name) catch; default end
14+
15+
@deprecate intrinsic_id(f::Function) isintrinsic(f) ? Intrinsic(f) : 0

src/intrinsics.jl

Whitespace-only changes.

src/util.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# utilities
22

3-
function unsafe_message(ptr)
4-
str = unsafe_string(ptr)
3+
function unsafe_message(ptr, args...)
4+
str = unsafe_string(ptr, args...)
55
API.LLVMDisposeMessage(ptr)
66
str
77
end

test/core.jl

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ LLVM.Module("SomeModule", ctx) do mod
680680
@test personality(fn) === nothing
681681
unsafe_delete!(mod, pers_fn)
682682

683-
@test intrinsic_id(fn) == 0
683+
@test !isintrinsic(fn)
684684

685685
@test callconv(fn) == LLVM.API.LLVMCCallConv
686686
callconv!(fn, LLVM.API.LLVMFastCallConv)
@@ -698,6 +698,37 @@ LLVM.Module("SomeModule", ctx) do mod
698698
end
699699
end
700700

701+
Context() do ctx
702+
LLVM.Module("SomeModule", ctx) do mod
703+
intr_ft = LLVM.FunctionType(LLVM.DoubleType(ctx), [LLVM.DoubleType(ctx)])
704+
intr_fn = LLVM.Function(mod, "llvm.sin.f64", intr_ft)
705+
@test isintrinsic(intr_fn)
706+
707+
intr = Intrinsic(intr_fn)
708+
show(devnull, intr)
709+
710+
if LLVM.version() >= v"8"
711+
@test isoverloaded(intr)
712+
713+
@test name(intr) == "llvm.sin"
714+
@test name(intr, [LLVM.DoubleType(ctx)]) == "llvm.sin.f64"
715+
716+
ft = FunctionType(intr, [LLVM.DoubleType(ctx)])
717+
@test ft isa FunctionType
718+
@test return_type(ft) == LLVM.DoubleType(ctx)
719+
720+
fn = LLVM.Function(mod, intr, [LLVM.DoubleType(ctx)])
721+
@test fn isa LLVM.Function
722+
@test eltype(llvmtype(fn)) == ft
723+
@test isintrinsic(fn)
724+
end
725+
726+
if LLVM.version() >= v"9"
727+
@test intr == Intrinsic("llvm.sin")
728+
end
729+
end
730+
end
731+
701732
# attributes
702733
Context() do ctx
703734
LLVM.Module("SomeModule", ctx) do mod

0 commit comments

Comments
 (0)