Skip to content

Commit

Permalink
Fix codegen for sizeof for arrays with non-power-of-2 types (#35900)
Browse files Browse the repository at this point in the history
  • Loading branch information
imciner2 authored May 17, 2020
1 parent 6fc59cd commit a383d61
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 2 deletions.
2 changes: 1 addition & 1 deletion base/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ size(V::SubArray) = (@_inline_meta; map(n->Int(unsafe_length(n)), axes(V)))

similar(V::SubArray, T::Type, dims::Dims) = similar(V.parent, T, dims)

sizeof(V::SubArray) = length(V) * sizeof(eltype(V))
sizeof(V::SubArray) = length(V) * elsize(V.parent)

copy(V::SubArray) = V.parent[V.indices...]

Expand Down
7 changes: 6 additions & 1 deletion src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2484,7 +2484,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
*ret = mark_julia_type(ctx, len, false, jl_long_type);
return true;
}
else if (jl_is_datatype(sty) && sty->name == jl_array_typename) {
else if (jl_is_array_type(sty)) {
auto len = emit_arraylen(ctx, obj);
jl_value_t *ety = jl_tparam0(sty);
Value *elsize;
Expand All @@ -2495,6 +2495,11 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
if (isboxed) {
elsize = ConstantInt::get(T_size, sizeof(void*));
}
else if (jl_is_primitivetype(ety)) {
// Primitive types should use the array element size, but
// this can be different from the type's size
elsize = ConstantInt::get(T_size, LLT_ALIGN(elsz, al));
}
else {
elsize = ConstantInt::get(T_size, elsz);
}
Expand Down
37 changes: 37 additions & 0 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -937,3 +937,40 @@ end
@testset "vcat with mixed elements" begin
@test vcat(Nothing[], [missing], [1.0], [Int8(1)]) isa Vector{Union{Missing, Nothing, Float64}}
end

@testset "sizeof" begin
let arrUInt8 = zeros(UInt8, 10)
@test sizeof(arrUInt8) == 10
@test Core.sizeof(arrUInt8) == 10
end

let arrUInt32 = zeros(UInt32, 10)
@test sizeof(arrUInt32) == 40
@test Core.sizeof(arrUInt32) == 40
end

let arrFloat64 = zeros(Float64, 10, 10)
@test sizeof(arrFloat64) == 800
@test Core.sizeof(arrFloat64) == 800
end

# Test union arrays (Issue #23321)
let arrUnion = Union{Int64, Cvoid}[rand(Bool) ? k : nothing for k = 1:10]
@test sizeof(arrUnion) == 80
@test Core.sizeof(arrUnion) == 80
end

# Test non-power of 2 types (Issue #35884)
primitive type UInt48 48 end
UInt48(x::UInt64) = Core.Intrinsics.trunc_int(UInt48, x)
UInt48(x::UInt32) = Core.Intrinsics.zext_int(UInt48, x)

a = UInt48(0x00000001);
b = UInt48(0x00000002);
c = UInt48(0x00000003);
let arrayOfUInt48 = [a, b, c]
f35884(x) = sizeof(x)
@test f35884(arrayOfUInt48) == 24
@test Core.sizeof(arrayOfUInt48) == 24
end
end
12 changes: 12 additions & 0 deletions test/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,18 @@ end
@test sizeof(view(zeros(UInt8, 10), 1:4)) == 4
@test sizeof(view(zeros(UInt8, 10), 1:3)) == 3
@test sizeof(view(zeros(Float64, 10, 10), 1:3, 2:6)) == 120

# Test non-power of 2 types (Issue #35884)
primitive type UInt48 48 end
UInt48(x::UInt64) = Core.Intrinsics.trunc_int(UInt48, x)
UInt48(x::UInt32) = Core.Intrinsics.zext_int(UInt48, x)

a = UInt48(0x00000001);
b = UInt48(0x00000002);
c = UInt48(0x00000003);
arrayOfUInt48 = [a, b, c];

@test sizeof(view(arrayOfUInt48, 1:2)) == 16
end


Expand Down

0 comments on commit a383d61

Please sign in to comment.