Skip to content

Commit 051f47b

Browse files
authored
codegen: mostly fix uses of undefined PhiNodes (#39236)
Unlike the rest of codegen, we permit PhiNodes to legally return undefined values, so we need to carefully skip those. Fixes #39232
1 parent 3c40768 commit 051f47b

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

src/codegen.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,7 +1376,7 @@ static inline jl_cgval_t update_julia_type(jl_codectx_t &ctx, const jl_cgval_t &
13761376
return jl_cgval_t(v, typ, NULL);
13771377
}
13781378

1379-
static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_value_t *typ);
1379+
static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_value_t *typ, Value **skip=nullptr);
13801380

13811381
// --- allocating local variables ---
13821382

@@ -1437,7 +1437,7 @@ static void CreateConditionalAbort(IRBuilder<> &irbuilder, Value *test)
14371437

14381438
#include "cgutils.cpp"
14391439

1440-
static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t &v, jl_value_t *typ)
1440+
static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t &v, jl_value_t *typ, Value **skip)
14411441
{
14421442
// previous value was a split union, compute new index, or box
14431443
Value *new_tindex = ConstantInt::get(T_int8, 0x80);
@@ -1462,6 +1462,10 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t &
14621462
// new value doesn't need to be boxed
14631463
// since it isn't part of the new union
14641464
t = true;
1465+
if (skip) {
1466+
Value *skip1 = ctx.builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, idx));
1467+
*skip = *skip ? ctx.builder.CreateOr(*skip, skip1) : skip1;
1468+
}
14651469
}
14661470
else {
14671471
// will actually need to box this element
@@ -1552,7 +1556,8 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t &
15521556
if (v.V == NULL) {
15531557
// v.V might be NULL if it was all ghost objects before
15541558
return jl_cgval_t(boxv, NULL, false, typ, new_tindex);
1555-
} else {
1559+
}
1560+
else {
15561561
Value *isboxv = ctx.builder.CreateIsNotNull(boxv);
15571562
Value *slotv;
15581563
MDNode *tbaa;
@@ -1584,7 +1589,7 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t &
15841589

15851590
// given a value marked with type `v.typ`, compute the mapping and/or boxing to return a value of type `typ`
15861591
// TODO: should this set TIndex when trivial (such as 0x80 or concrete types) ?
1587-
static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_value_t *typ)
1592+
static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_value_t *typ, Value **skip)
15881593
{
15891594
if (typ == (jl_value_t*)jl_typeofbottom_type)
15901595
return ghostValue(typ); // normalize TypeofBottom to Type{Union{}}
@@ -1595,6 +1600,7 @@ static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_
15951600
return ghostValue(typ);
15961601
Value *new_tindex = NULL;
15971602
if (jl_is_concrete_type(typ)) {
1603+
assert(skip == nullptr && "skip only valid for union type return");
15981604
if (v.TIndex && !jl_is_pointerfree(typ)) {
15991605
// discovered that this union-split type must actually be isboxed
16001606
if (v.Vboxed) {
@@ -1617,7 +1623,7 @@ static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_
16171623
else {
16181624
bool makeboxed = false;
16191625
if (v.TIndex) {
1620-
return convert_julia_type_union(ctx, v, typ);
1626+
return convert_julia_type_union(ctx, v, typ, skip);
16211627
}
16221628
else if (!v.isboxed && jl_is_uniontype(typ)) {
16231629
// previous value was unboxed (leaftype), statically compute union tindex
@@ -1637,6 +1643,11 @@ static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_
16371643
else if (jl_subtype(v.typ, typ)) {
16381644
makeboxed = true;
16391645
}
1646+
else if (skip) {
1647+
// undef
1648+
*skip = ConstantInt::get(T_int1, 1);
1649+
return jl_cgval_t();
1650+
}
16401651
else {
16411652
// unreachable
16421653
CreateTrap(ctx.builder);
@@ -6919,12 +6930,16 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t>
69196930
V = boxed(ctx, val);
69206931
}
69216932
else {
6933+
// XXX: must emit undef here (rather than a bitcast or
6934+
// load of val) if the runtime type of val isn't phiType
69226935
V = emit_unbox(ctx, VN->getType(), val, phiType);
69236936
}
69246937
VN->addIncoming(V, ctx.builder.GetInsertBlock());
69256938
assert(!TindexN);
69266939
}
69276940
else if (dest && val.typ != (jl_value_t*)jl_bottom_type) {
6941+
// XXX: must emit undef here (rather than a bitcast or
6942+
// load of val) if the runtime type of val isn't phiType
69286943
assert(lty != T_prjlvalue);
69296944
(void)emit_unbox(ctx, lty, val, phiType, maybe_decay_tracked(ctx, dest));
69306945
}
@@ -6957,7 +6972,10 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t>
69576972
}
69586973
}
69596974
else {
6960-
jl_cgval_t new_union = convert_julia_type(ctx, val, phiType);
6975+
Value *skip = NULL;
6976+
// must compute skip here, since the runtime type of val might not be in phiType
6977+
// caution: only Phi and PhiC are allowed to do this (and maybe sometimes Pi)
6978+
jl_cgval_t new_union = convert_julia_type(ctx, val, phiType, &skip);
69616979
RTindex = new_union.TIndex;
69626980
if (!RTindex) {
69636981
assert(new_union.isboxed && new_union.Vboxed && "convert_julia_type failed");
@@ -6972,11 +6990,12 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t>
69726990
if (VN)
69736991
V = new_union.Vboxed ? new_union.Vboxed : V_rnull;
69746992
if (dest) { // basically, if !ghost union
6975-
Value *skip = NULL;
6976-
if (new_union.Vboxed != nullptr)
6977-
skip = ctx.builder.CreateICmpNE( // if 0x80 is set, we won't select this slot anyways
6993+
if (new_union.Vboxed != nullptr) {
6994+
Value *isboxed = ctx.builder.CreateICmpNE( // if 0x80 is set, we won't select this slot anyways
69786995
ctx.builder.CreateAnd(RTindex, ConstantInt::get(T_int8, 0x80)),
69796996
ConstantInt::get(T_int8, 0));
6997+
skip = skip ? ctx.builder.CreateOr(isboxed, skip) : isboxed;
6998+
}
69806999
emit_unionmove(ctx, dest, tbaa_arraybuf, new_union, skip);
69817000
}
69827001
}

test/compiler/codegen.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,3 +512,13 @@ let a = Core.Intrinsics.trunc_int(UInt24, 3),
512512
@test sizeof(Union{UInt8,UInt24}) == 3
513513
@test sizeof(Base.RefValue{Union{UInt8,UInt24}}) == 8
514514
end
515+
516+
# issue #39232
517+
function f39232(a)
518+
z = Any[]
519+
for (i, ai) in enumerate(a)
520+
push!(z, ai)
521+
end
522+
return z
523+
end
524+
@test f39232((+, -)) == Any[+, -]

0 commit comments

Comments
 (0)