diff --git a/src/cgutils.cpp b/src/cgutils.cpp index bb0e15ed7363c..58bfb958a917c 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -2472,6 +2472,27 @@ static Value *compute_box_tindex(jl_codectx_t &ctx, Value *datatype, jl_value_t return tindex; } +// Returns typeof(v), or null if v is a null pointer at run time. +// This is used when the value might have come from an undefined variable, +// yet we try to read its type to compute a union index when moving the value. +static Value *emit_typeof_or_null(jl_codectx_t &ctx, Value *v) +{ + BasicBlock *nonnull = BasicBlock::Create(jl_LLVMContext, "nonnull", ctx.f); + BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "postnull", ctx.f); + Value *isnull = ctx.builder.CreateICmpEQ(v, Constant::getNullValue(v->getType())); + ctx.builder.CreateCondBr(isnull, postBB, nonnull); + BasicBlock *entry = ctx.builder.GetInsertBlock(); + ctx.builder.SetInsertPoint(nonnull); + Value *typof = emit_typeof(ctx, v); + ctx.builder.CreateBr(postBB); + nonnull = ctx.builder.GetInsertBlock(); // could have changed + ctx.builder.SetInsertPoint(postBB); + PHINode *ti = ctx.builder.CreatePHI(typof->getType(), 2); + ti->addIncoming(Constant::getNullValue(typof->getType()), entry); + ti->addIncoming(typof, nonnull); + return ti; +} + // get the runtime tindex value, assuming val is already converted to type typ if it has a TIndex static Value *compute_tindex_unboxed(jl_codectx_t &ctx, const jl_cgval_t &val, jl_value_t *typ) { @@ -2482,9 +2503,12 @@ static Value *compute_tindex_unboxed(jl_codectx_t &ctx, const jl_cgval_t &val, j if (val.TIndex) return ctx.builder.CreateAnd(val.TIndex, ConstantInt::get(T_int8, 0x7f)); - if (val.isboxed) - return compute_box_tindex(ctx, emit_typeof_boxed(ctx, val), val.typ, typ); - return compute_box_tindex(ctx, emit_typeof_boxed(ctx, val), val.typ, typ); + Value *typof; + if (val.isboxed && !jl_is_concrete_type(val.typ) && !jl_is_type_type(val.typ)) + typof = emit_typeof_or_null(ctx, val.V); + else + typof = emit_typeof_boxed(ctx, val); + return compute_box_tindex(ctx, typof, val.typ, typ); } static void union_alloca_type(jl_uniontype_t *ut, diff --git a/src/codegen.cpp b/src/codegen.cpp index b3acb943b3150..4be8510adcbea 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1504,11 +1504,13 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t & // actually need it. Value *union_box_dt = NULL; BasicBlock *union_isaBB = NULL; + BasicBlock *post_union_isaBB = NULL; auto maybe_setup_union_isa = [&]() { if (!union_isaBB) { union_isaBB = BasicBlock::Create(jl_LLVMContext, "union_isa", ctx.f); ctx.builder.SetInsertPoint(union_isaBB); - union_box_dt = emit_typeof(ctx, v.Vboxed); + union_box_dt = emit_typeof_or_null(ctx, v.Vboxed); + post_union_isaBB = ctx.builder.GetInsertBlock(); } }; @@ -1540,7 +1542,7 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t & ctx.builder.SetInsertPoint(postBB); PHINode *tindex_phi = ctx.builder.CreatePHI(T_int8, 2); tindex_phi->addIncoming(new_tindex, currBB); - tindex_phi->addIncoming(union_box_tindex, union_isaBB); + tindex_phi->addIncoming(union_box_tindex, post_union_isaBB); new_tindex = tindex_phi; } } diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index 47f419d9937a2..97a9d45d7ecf3 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -553,3 +553,11 @@ end end @test occursin("llvm.julia.gc_preserve_begin", get_llvm(f4, Tuple{Bool}, true, false, false)) end + +# issue #32843 +function f32843(vals0, v) + (length(vals0) > 1) && (vals = v[1]) + (length(vals0) == 1 && vals0[1]==1) && (vals = 1:2) + vals +end +@test_throws UndefVarError f32843([6], Vector[[1]])