Skip to content

Commit dbb7828

Browse files
committed
fix #37974, struct layout of odd-size primitive types
1 parent d922cfc commit dbb7828

File tree

5 files changed

+28
-7
lines changed

5 files changed

+28
-7
lines changed

base/compiler/tfuncs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ function sizeof_tfunc(@nospecialize(x),)
380380
x = unwrap_unionall(t)
381381
if exact && isa(x, Union)
382382
isinline, sz, _ = uniontype_layout(x)
383-
return isinline ? Const(Int(sz)) : Bottom
383+
return isinline ? Const(Int(Core.sizeof(x))) : Bottom
384384
end
385385
isa(x, DataType) || return Int
386386
(isconcretetype(x) || isprimitivetype(x)) && return _const_sizeof(x)

src/builtins.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,8 @@ JL_CALLABLE(jl_f_sizeof)
399399
jl_value_t *x = args[0];
400400
if (jl_is_unionall(x) || jl_is_uniontype(x)) {
401401
x = jl_unwrap_unionall(x);
402-
size_t elsize = 0, al = 0;
403-
int isinline = jl_islayout_inline(x, &elsize, &al);
402+
size_t elsize = 0;
403+
int isinline = jl_uniontype_size(x, &elsize);
404404
if (isinline)
405405
return jl_box_long(elsize);
406406
if (!jl_is_datatype(x))

src/datatype.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,20 +235,23 @@ STATIC_INLINE void jl_maybe_allocate_singleton_instance(jl_datatype_t *st)
235235
}
236236
}
237237

238-
static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbytes, size_t *align) JL_NOTSAFEPOINT
238+
static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbytes, size_t *align, int asfield) JL_NOTSAFEPOINT
239239
{
240240
if (jl_is_uniontype(ty)) {
241-
unsigned na = union_isinlinable(((jl_uniontype_t*)ty)->a, 1, nbytes, align);
241+
unsigned na = union_isinlinable(((jl_uniontype_t*)ty)->a, 1, nbytes, align, asfield);
242242
if (na == 0)
243243
return 0;
244-
unsigned nb = union_isinlinable(((jl_uniontype_t*)ty)->b, 1, nbytes, align);
244+
unsigned nb = union_isinlinable(((jl_uniontype_t*)ty)->b, 1, nbytes, align, asfield);
245245
if (nb == 0)
246246
return 0;
247247
return na + nb;
248248
}
249249
if (jl_is_datatype(ty) && jl_datatype_isinlinealloc(ty) && (!pointerfree || ((jl_datatype_t*)ty)->layout->npointers == 0)) {
250250
size_t sz = jl_datatype_size(ty);
251251
size_t al = jl_datatype_align(ty);
252+
// primitive types in struct slots need their sizes aligned. issue #37974
253+
if (asfield && jl_is_primitivetype(ty))
254+
sz = LLT_ALIGN(sz, al);
252255
if (*nbytes < sz)
253256
*nbytes = sz;
254257
if (*align < al)
@@ -258,9 +261,15 @@ static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbyte
258261
return 0;
259262
}
260263

264+
int jl_uniontype_size(jl_value_t *ty, size_t *sz) JL_NOTSAFEPOINT
265+
{
266+
size_t al = 0;
267+
return union_isinlinable(ty, 0, sz, &al, 0) != 0;
268+
}
269+
261270
JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al) JL_NOTSAFEPOINT
262271
{
263-
unsigned countbits = union_isinlinable(eltype, 0, fsz, al);
272+
unsigned countbits = union_isinlinable(eltype, 0, fsz, al, 1);
264273
return (countbits > 0 && countbits < 127) ? countbits : 0;
265274
}
266275

src/julia.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,7 @@ JL_DLLEXPORT void jl_set_nth_field(jl_value_t *v, size_t i,
13981398
JL_DLLEXPORT int jl_field_isdefined(jl_value_t *v, size_t i) JL_NOTSAFEPOINT;
13991399
JL_DLLEXPORT jl_value_t *jl_get_field(jl_value_t *o, const char *fld);
14001400
JL_DLLEXPORT jl_value_t *jl_value_ptr(jl_value_t *a);
1401+
int jl_uniontype_size(jl_value_t *ty, size_t *sz) JL_NOTSAFEPOINT;
14011402
JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al) JL_NOTSAFEPOINT;
14021403

14031404
// arrays

test/compiler/codegen.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,3 +500,14 @@ end
500500
let f(@nospecialize(x)) = x===Base.ImmutableDict(Int128=>:big)
501501
@test !f(Dict(Int=>Int))
502502
end
503+
504+
# issue #37974
505+
primitive type UInt24 24 end
506+
let a = Core.Intrinsics.trunc_int(UInt24, 3),
507+
f(t) = t[2]
508+
@test f((a, true)) === true
509+
@test f((a, false)) === false
510+
@test sizeof(Tuple{UInt24,Bool}) == 8
511+
@test sizeof(UInt24) == 3
512+
@test sizeof(Union{UInt8,UInt24}) == 3
513+
end

0 commit comments

Comments
 (0)