Skip to content

Commit 65fddfd

Browse files
jpsamaroovchuravy
andauthored
Add generated Interop.addrspacecast for LLVMPtr (#322)
Base's reinterpret only calls bitcast, which is insufficient when the source and destination pointers have different address spaces. Co-authored-by: Valentin Churavy <[email protected]>
1 parent 9f9d2fa commit 65fddfd

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

src/interop/pointer.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,31 @@ Base.:(+)(x::Integer, y::LLVMPtr) = y + x
114114
Base.unsigned(x::LLVMPtr) = UInt(x)
115115
Base.signed(x::LLVMPtr) = Int(x)
116116

117+
@generated function addrspacecast(::Type{LLVMPtr{TDest, ASDest}}, src::LLVMPtr{TSrc, ASSrc}) where {TDest, ASDest, TSrc, ASSrc}
118+
@dispose ctx=Context() begin
119+
T_dest = convert(LLVMType, LLVMPtr{TDest, ASDest}; ctx)
120+
T_src = convert(LLVMType, LLVMPtr{TSrc, ASSrc}; ctx)
121+
122+
llvm_f, _ = create_function(T_dest, [T_src])
123+
mod = LLVM.parent(llvm_f)
124+
125+
@dispose builder=Builder(ctx) begin
126+
entry = BasicBlock(llvm_f, "entry"; ctx)
127+
position!(builder, entry)
128+
129+
dest_ptr = if ASDest != ASSrc
130+
addrspacecast!(builder, parameters(llvm_f)[1], T_dest)
131+
else
132+
parameters(llvm_f)[1]
133+
end
134+
ret!(builder, bitcast!(builder, dest_ptr, T_dest))
135+
end
136+
137+
call_function(llvm_f, LLVMPtr{TDest, ASDest},
138+
Tuple{LLVMPtr{TSrc, ASSrc}}, :src)
139+
end
140+
end
141+
117142

118143
# type-preserving ccall
119144

test/interop.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,19 @@ end
202202
@test contains(ir, r"load i64, i64\* %\d+, align 4")
203203
end
204204

205+
@testset "reinterpret with addrspacecast" begin
206+
ptr = reinterpret(Core.LLVMPtr{Int64, 4}, 0)
207+
for eltype_dest in (Int64, Int32), AS_dest in (4, 3)
208+
T_dest = Core.LLVMPtr{eltype_dest, AS_dest}
209+
ir = sprint(io->code_llvm(io, LLVM.Interop.addrspacecast, Tuple{Type{T_dest}, typeof(ptr)}))
210+
if AS_dest == 3
211+
@test contains(ir, r"addrspacecast i8 addrspace\(4\)\* %\d+ to i8 addrspace\(3\)\*")
212+
else
213+
@test !contains(ir, r"addrspacecast i8 addrspace\(4\)\* %\d+ to i8 addrspace\(3\)\*")
214+
end
215+
end
216+
end
217+
205218
@testset "reinterpret(Nothing, nothing)" begin
206219
ptr = reinterpret(Core.LLVMPtr{Nothing,0}, C_NULL)
207220
@test unsafe_load(ptr) === nothing

0 commit comments

Comments
 (0)