Skip to content

Commit ed01ee0

Browse files
authored
ccall: handle Union appearing as a field-type without crashing (#46787)
We disallow union as the direct type, so perhaps we should disallow it as a field-type also, but since we do allow references in those cases typically, we will allow this also. Also DRY the emit_global code, since it had bit-rotted relative to the usual code path through emit_globalref (and apparently could still be run though for handling the first argument to cfunction). Fix #46786
1 parent bb7c7eb commit ed01ee0

File tree

6 files changed

+50
-29
lines changed

6 files changed

+50
-29
lines changed

src/abi_aarch64.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ Type *get_llvm_vectype(jl_datatype_t *dt, LLVMContext &ctx) const
4343
// the homogeneity check.
4444
jl_datatype_t *ft0 = (jl_datatype_t*)jl_field_type(dt, 0);
4545
// `ft0` should be a `VecElement` type and the true element type
46-
// should be a primitive type
47-
if (ft0->name != jl_vecelement_typename ||
48-
((jl_datatype_t*)jl_field_type(ft0, 0))->layout->nfields)
46+
// should be a primitive type (nfields == 0)
47+
if (!jl_is_datatype(ft0) || ft0->name != jl_vecelement_typename)
48+
return nullptr;
49+
jl_datatype_t *ft00 = (jl_datatype_t*)jl_field_type(ft0, 0);
50+
if (!jl_is_datatype(ft00) || ft00->layout->nfields)
4951
return nullptr;
5052
for (size_t i = 1; i < nfields; i++) {
5153
if (jl_field_type(dt, i) != (jl_value_t*)ft0) {
@@ -120,15 +122,17 @@ bool isHFAorHVA(jl_datatype_t *dt, size_t dsz, size_t &nele, ElementType &ele, L
120122
// For composite types, find the first non zero sized member
121123
size_t i;
122124
size_t fieldsz;
123-
for (i = 0;i < nfields;i++) {
125+
for (i = 0; i < nfields; i++) {
124126
if ((fieldsz = jl_field_size(dt, i))) {
125127
break;
126128
}
127129
}
128130
assert(i < nfields);
129-
// If there's only one non zero sized member, try again on this member
131+
// If there's only one non-zero sized member, try again on this member
130132
if (fieldsz == dsz) {
131133
dt = (jl_datatype_t*)jl_field_type(dt, i);
134+
if (!jl_is_datatype(dt))
135+
return false;
132136
continue;
133137
}
134138
if (Type *vectype = get_llvm_vectype(dt, ctx)) {
@@ -140,11 +144,13 @@ bool isHFAorHVA(jl_datatype_t *dt, size_t dsz, size_t &nele, ElementType &ele, L
140144
return true;
141145
}
142146
// Otherwise, process each members
143-
for (;i < nfields;i++) {
147+
for (; i < nfields; i++) {
144148
size_t fieldsz = jl_field_size(dt, i);
145149
if (fieldsz == 0)
146150
continue;
147151
jl_datatype_t *fieldtype = (jl_datatype_t*)jl_field_type(dt, i);
152+
if (!jl_is_datatype(dt))
153+
return false;
148154
// Check element count.
149155
// This needs to be done after the zero size member check
150156
if (nele > 3 || !isHFAorHVA(fieldtype, fieldsz, nele, ele, ctx)) {

src/abi_arm.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ size_t isLegalHA(jl_datatype_t *dt, Type *&base, LLVMContext &ctx) const
9191
size_t parent_members = jl_datatype_nfields(dt);
9292
for (size_t i = 0; i < parent_members; ++i) {
9393
jl_datatype_t *fdt = (jl_datatype_t*)jl_field_type(dt,i);
94+
if (!jl_is_datatype(fdt))
95+
return 0;
9496

9597
Type *T = isLegalHAType(fdt, ctx);
9698
if (T)

src/abi_ppc64le.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ struct ABI_PPC64leLayout : AbiLayout {
4444
// count the homogeneous floating aggregate size (saturating at max count of 8)
4545
unsigned isHFA(jl_datatype_t *ty, jl_datatype_t **ty0, bool *hva) const
4646
{
47+
if (jl_datatype_size(ty) > 128 || ty->layout->npointers || ty->layout->haspadding)
48+
return 9;
49+
4750
size_t i, l = ty->layout->nfields;
4851
// handle homogeneous float aggregates
4952
if (l == 0) {
@@ -52,7 +55,7 @@ unsigned isHFA(jl_datatype_t *ty, jl_datatype_t **ty0, bool *hva) const
5255
*hva = false;
5356
if (*ty0 == NULL)
5457
*ty0 = ty;
55-
else if (*hva || ty->size != (*ty0)->size)
58+
else if (*hva || jl_datatype_size(ty) != jl_datatype_size(*ty0))
5659
return 9;
5760
return 1;
5861
}
@@ -69,7 +72,7 @@ unsigned isHFA(jl_datatype_t *ty, jl_datatype_t **ty0, bool *hva) const
6972
*hva = true;
7073
if (*ty0 == NULL)
7174
*ty0 = ty;
72-
else if (!*hva || ty->size != (*ty0)->size)
75+
else if (!*hva || jl_datatype_size(ty) != jl_datatype_size(*ty0))
7376
return 9;
7477
for (i = 1; i < l; i++) {
7578
jl_datatype_t *fld = (jl_datatype_t*)jl_field_type(ty, i);

src/abi_x86_64.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ void classifyType(Classification& accum, jl_datatype_t *dt, uint64_t offset) con
153153
jl_value_t *ty = jl_field_type(dt, i);
154154
if (jl_field_isptr(dt, i))
155155
ty = (jl_value_t*)jl_voidpointer_type;
156+
else if (!jl_is_datatype(ty)) { // inline union
157+
accum.addField(offset, Memory);
158+
continue;
159+
}
156160
classifyType(accum, (jl_datatype_t*)ty, offset + jl_field_offset(dt, i));
157161
}
158162
}

src/codegen.cpp

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4258,26 +4258,6 @@ static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i)
42584258
return mark_julia_type(ctx, sp, true, jl_any_type);
42594259
}
42604260

4261-
static jl_cgval_t emit_global(jl_codectx_t &ctx, jl_sym_t *sym)
4262-
{
4263-
jl_binding_t *jbp = NULL;
4264-
Value *bp = global_binding_pointer(ctx, ctx.module, sym, &jbp, false);
4265-
if (bp == NULL)
4266-
return jl_cgval_t();
4267-
if (jbp && jbp->value != NULL) {
4268-
if (jbp->constp)
4269-
return mark_julia_const(ctx, jbp->value);
4270-
// double-check that a global variable is actually defined. this
4271-
// can be a problem in parallel when a definition is missing on
4272-
// one machine.
4273-
LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)));
4274-
v->setOrdering(AtomicOrdering::Unordered);
4275-
tbaa_decorate(ctx.tbaa().tbaa_binding, v);
4276-
return mark_julia_type(ctx, v, true, jl_any_type);
4277-
}
4278-
return emit_checked_var(ctx, bp, sym, false, ctx.tbaa().tbaa_binding);
4279-
}
4280-
42814261
static jl_cgval_t emit_isdefined(jl_codectx_t &ctx, jl_value_t *sym)
42824262
{
42834263
Value *isnull = NULL;
@@ -4928,7 +4908,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_
49284908
{
49294909
if (jl_is_symbol(expr)) {
49304910
jl_sym_t *sym = (jl_sym_t*)expr;
4931-
return emit_global(ctx, sym);
4911+
return emit_globalref(ctx, ctx.module, sym, AtomicOrdering::Unordered);
49324912
}
49334913
if (jl_is_slot(expr) || jl_is_argument(expr)) {
49344914
return emit_local(ctx, expr);

test/ccall.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,6 +1590,32 @@ function caller22734(ptr)
15901590
end
15911591
@test caller22734(ptr22734) === 32.0
15921592

1593+
# issue #46786 -- non-isbitstypes passed "by-value"
1594+
struct NonBits46786
1595+
x::Union{Int16,NTuple{3,UInt8}}
1596+
end
1597+
let ptr = @cfunction(identity, NonBits46786, (NonBits46786,))
1598+
obj1 = NonBits46786((0x01,0x02,0x03))
1599+
obj2 = ccall(ptr, NonBits46786, (NonBits46786,), obj1)
1600+
@test obj1 === obj2
1601+
end
1602+
let ptr = @cfunction(identity, Base.RefValue{NonBits46786}, (Base.RefValue{NonBits46786},))
1603+
obj1 = Base.RefValue(NonBits46786((0x01,0x02,0x03)))
1604+
obj2 = ccall(ptr, Base.RefValue{NonBits46786}, (Base.RefValue{NonBits46786},), obj1)
1605+
@test obj1 !== obj2
1606+
@test obj1.x === obj2.x
1607+
end
1608+
1609+
mutable struct MutNonBits46786
1610+
x::Union{Int16,NTuple{3,UInt8}}
1611+
end
1612+
let ptr = @cfunction(identity, MutNonBits46786, (MutNonBits46786,))
1613+
obj1 = MutNonBits46786((0x01,0x02,0x03))
1614+
obj2 = ccall(ptr, MutNonBits46786, (MutNonBits46786,), obj1)
1615+
@test obj1 !== obj2
1616+
@test obj1.x === obj2.x
1617+
end
1618+
15931619
# 26297#issuecomment-371165725
15941620
# test that the first argument to cglobal is recognized as a tuple literal even through
15951621
# macro expansion

0 commit comments

Comments
 (0)