What? The only things you need to stay safe from segfaults is:
- Only do this with bitstypes
- Don’t forget that the unsafe_wrap thingy doesn’t keep the underlying allocation alive. You may need to gc_preserve the underlying thing.
It seems to work.
A small issue is that julia aliasing rules used to say that Memory{UInt64} and Memory{Float64} are forbidden from aliasing, i.e. sharing memory.
Since you are lying to the compiler about the TBAA class of the underlying memory, the optimizer could theoretically miscompile your code.
You have a potential aliasing issue when you have two accesses to the same address through two differently typed Memory, and at least one of them is a write.
You can fix the aliasing issue by telling the compiler that you’re doing something fishy, i.e. by inserting a barrier between any two such accesses. The barrier can be emitted as
julia> membarrier()=Base.llvmcall("""call void asm ";","~{memory}"()
ret void""", Cvoid, Tuple{},)
This is the same kind of barrier that you need if you play games with virtual memory, like mapping the same physical memory multiple times with different virtual addresses. And the same barrier you would need in C, C++, rust.
…all that being said, I currently cannot reproduce TBAA-based optimizations.
For example
julia> function foo(a::Vector{Int},b::Vector{UInt32},n)
@inbounds for i=1:n
a[1] += 1
b[1] += UInt32(1)
end
nothing
end
should run in O(1), i.e. llvm should remove the loop. But llvm fails to figure out that a and b cannot alias, and it also fails to emit a check whether they alias.