|
17 | 17 | Expr(:block, Expr(:meta,:inline), :(ccall(:jl_value_ptr, Ref{$T}, (Ptr{Cvoid},), unsafe_load(Base.unsafe_convert(Ptr{Ptr{Cvoid}}, p)))))
|
18 | 18 | end
|
19 | 19 | end
|
| 20 | +@inline load(p::Ptr{UInt}, ::Type{T}) where {T} = load(reinterpret(Ptr{T}, p)) |
20 | 21 | @generated function store!(p::Ptr{T}, v::T) where {T}
|
21 | 22 | if Base.allocatedinline(T)
|
22 | 23 | Expr(:block, Expr(:meta,:inline), :(unsafe_store!(p, v); return nothing))
|
|
33 | 34 | @inline _preserve_buffer(a::A, p::A) where {A<:AbstractArray} = a
|
34 | 35 | @inline _preserve_buffer(a::A, p::P) where {A,P} = p
|
35 | 36 |
|
| 37 | +function load_aggregate(::Type{T}, offset::Int) where {T} |
| 38 | + numfields = fieldcount(T) |
| 39 | + call = (T <: Tuple) ? Expr(:tuple) : Expr(:new, T) |
| 40 | + for f ∈ 1:numfields |
| 41 | + TF = fieldtype(T, f) |
| 42 | + if Base.issingletontype(TF) |
| 43 | + push!(call.args, TF.instance) |
| 44 | + elseif fieldcount(TF) ≡ 0 |
| 45 | + ptr = :(p + (offset + $offset)) |
| 46 | + ptr = TF === UInt ? ptr : :(reinterpret(Ptr{$TF}, $ptr)) |
| 47 | + push!(call.args, :(load($ptr))) |
| 48 | + offset += offsetsize(TF) |
| 49 | + else |
| 50 | + arg, offset = load_aggregate(TF, offset) |
| 51 | + push!(call.args, arg) |
| 52 | + end |
| 53 | + end |
| 54 | + return call, offset |
| 55 | +end |
| 56 | +@generated function load(p::Ptr{UInt}, ::Type{T}, offset::Int) where {T} |
| 57 | + if Base.issingletontype(T) |
| 58 | + call = Expr(:tuple, :offset, T.instance) |
| 59 | + elseif fieldcount(T) ≡ 0 |
| 60 | + ptr = :(p + offset) |
| 61 | + ptr = T === UInt ? ptr : :(reinterpret(Ptr{$T}, $ptr)) |
| 62 | + call = :(((offset + $(offsetsize(T)), load($ptr)))) |
| 63 | + else |
| 64 | + call, off = load_aggregate(T, 0) |
| 65 | + call = Expr(:tuple, :(offset + $off), call) |
| 66 | + end |
| 67 | + Expr(:block, Expr(:meta,:inline), call) |
| 68 | +end |
| 69 | + |
| 70 | +function store_aggregate!(q::Expr, sym, ::Type{T}, offset::Int) where {T} |
| 71 | + gf = GlobalRef(Core,:getfield) |
| 72 | + for f ∈ 1:fieldcount(T) |
| 73 | + TF = fieldtype(T, f) |
| 74 | + Base.issingletontype(TF) && continue |
| 75 | + gfcall = Expr(:call, gf, sym, f) |
| 76 | + if fieldcount(TF) ≡ 0 |
| 77 | + ptr = :(p + (offset + $offset)) |
| 78 | + ptr = TF === UInt ? ptr : :(reinterpret(Ptr{$TF}, $ptr)) |
| 79 | + push!(q.args, :(store!($ptr, $gfcall))) |
| 80 | + offset += offsetsize(TF) |
| 81 | + else |
| 82 | + newsym = gensym(sym) |
| 83 | + push!(q.args, Expr(:(=), newsym, gfcall)) |
| 84 | + offset = store_aggregate!(q, newsym, TF, offset) |
| 85 | + end |
| 86 | + end |
| 87 | + return offset |
| 88 | +end |
| 89 | +@generated function store!(p::Ptr{UInt}, x::T, offset::Int) where {T} |
| 90 | + Base.issingletontype(T) && return :offset |
| 91 | + body = Expr(:block, Expr(:meta,:inline)) |
| 92 | + if fieldcount(T) ≡ 0 |
| 93 | + ptr = :(p + offset) |
| 94 | + ptr = T === UInt ? ptr : :(reinterpret(Ptr{$T}, $ptr)) |
| 95 | + push!(body.args, :(store!($ptr, x))) |
| 96 | + off = offsetsize(T) |
| 97 | + else |
| 98 | + off = store_aggregate!(body, :x, T, 0) |
| 99 | + end |
| 100 | + push!(body.args, Expr(:call, +, :offset, off)) |
| 101 | + return body |
| 102 | +end |
| 103 | + |
36 | 104 | end
|
0 commit comments