diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index ac8aa0c639dc5..3b5f53a27c516 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -380,7 +380,7 @@ function sizeof_tfunc(@nospecialize(x),) x = unwrap_unionall(t) if exact && isa(x, Union) isinline, sz, _ = uniontype_layout(x) - return isinline ? Const(Int(sz)) : Bottom + return isinline ? Const(Int(Core.sizeof(x))) : Bottom end isa(x, DataType) || return Int (isconcretetype(x) || isprimitivetype(x)) && return _const_sizeof(x) diff --git a/src/builtins.c b/src/builtins.c index 6d5f3f2779a12..8cbce6c5b6188 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -399,8 +399,8 @@ JL_CALLABLE(jl_f_sizeof) jl_value_t *x = args[0]; if (jl_is_unionall(x) || jl_is_uniontype(x)) { x = jl_unwrap_unionall(x); - size_t elsize = 0, al = 0; - int isinline = jl_islayout_inline(x, &elsize, &al); + size_t elsize = 0; + int isinline = jl_uniontype_size(x, &elsize); if (isinline) return jl_box_long(elsize); if (!jl_is_datatype(x)) diff --git a/src/datatype.c b/src/datatype.c index eeceae946b74e..3428e7479e9ed 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -235,13 +235,13 @@ STATIC_INLINE void jl_maybe_allocate_singleton_instance(jl_datatype_t *st) } } -static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbytes, size_t *align) JL_NOTSAFEPOINT +static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbytes, size_t *align, int asfield) JL_NOTSAFEPOINT { if (jl_is_uniontype(ty)) { - unsigned na = union_isinlinable(((jl_uniontype_t*)ty)->a, 1, nbytes, align); + unsigned na = union_isinlinable(((jl_uniontype_t*)ty)->a, 1, nbytes, align, asfield); if (na == 0) return 0; - unsigned nb = union_isinlinable(((jl_uniontype_t*)ty)->b, 1, nbytes, align); + unsigned nb = union_isinlinable(((jl_uniontype_t*)ty)->b, 1, nbytes, align, asfield); if (nb == 0) return 0; return na + nb; @@ -249,6 +249,9 @@ static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbyte if (jl_is_datatype(ty) && jl_datatype_isinlinealloc(ty) && (!pointerfree || ((jl_datatype_t*)ty)->layout->npointers == 0)) { size_t sz = jl_datatype_size(ty); size_t al = jl_datatype_align(ty); + // primitive types in struct slots need their sizes aligned. issue #37974 + if (asfield && jl_is_primitivetype(ty)) + sz = LLT_ALIGN(sz, al); if (*nbytes < sz) *nbytes = sz; if (*align < al) @@ -258,9 +261,15 @@ static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbyte return 0; } +int jl_uniontype_size(jl_value_t *ty, size_t *sz) JL_NOTSAFEPOINT +{ + size_t al = 0; + return union_isinlinable(ty, 0, sz, &al, 0) != 0; +} + JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al) JL_NOTSAFEPOINT { - unsigned countbits = union_isinlinable(eltype, 0, fsz, al); + unsigned countbits = union_isinlinable(eltype, 0, fsz, al, 1); return (countbits > 0 && countbits < 127) ? countbits : 0; } diff --git a/src/julia.h b/src/julia.h index 9b55c5db0cf98..2cd47e80f6a37 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1398,6 +1398,7 @@ JL_DLLEXPORT void jl_set_nth_field(jl_value_t *v, size_t i, JL_DLLEXPORT int jl_field_isdefined(jl_value_t *v, size_t i) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_get_field(jl_value_t *o, const char *fld); JL_DLLEXPORT jl_value_t *jl_value_ptr(jl_value_t *a); +int jl_uniontype_size(jl_value_t *ty, size_t *sz) JL_NOTSAFEPOINT; JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al) JL_NOTSAFEPOINT; // arrays diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index 2ccffc40b2f16..9b147fd0b571b 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -500,3 +500,15 @@ end let f(@nospecialize(x)) = x===Base.ImmutableDict(Int128=>:big) @test !f(Dict(Int=>Int)) end + +# issue #37974 +primitive type UInt24 24 end +let a = Core.Intrinsics.trunc_int(UInt24, 3), + f(t) = t[2] + @test f((a, true)) === true + @test f((a, false)) === false + @test sizeof(Tuple{UInt24,Bool}) == 8 + @test sizeof(UInt24) == 3 + @test sizeof(Union{UInt8,UInt24}) == 3 + @test sizeof(Base.RefValue{Union{UInt8,UInt24}}) == 8 +end