@@ -761,7 +761,7 @@ static bool is_uniontype_allunboxed(jl_value_t *typ)
761
761
return for_each_uniontype_small ([&](unsigned , jl_datatype_t *) {}, typ, counter);
762
762
}
763
763
764
- static Value *emit_typeof_boxed (jl_codectx_t &ctx, const jl_cgval_t &p);
764
+ static Value *emit_typeof_boxed (jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull= false );
765
765
766
766
static unsigned get_box_tindex (jl_datatype_t *jt, jl_value_t *ut)
767
767
{
@@ -814,15 +814,9 @@ static LoadInst *emit_nthptr_recast(jl_codectx_t &ctx, Value *v, ssize_t n, MDNo
814
814
}
815
815
816
816
static Value *boxed (jl_codectx_t &ctx, const jl_cgval_t &v);
817
+ static Value *emit_typeof (jl_codectx_t &ctx, Value *v, bool maybenull);
817
818
818
- // Returns ctx.types().T_prjlvalue
819
- static Value *emit_typeof (jl_codectx_t &ctx, Value *tt)
820
- {
821
- assert (tt != NULL && !isa<AllocaInst>(tt) && " expected a conditionally boxed value" );
822
- return ctx.builder .CreateCall (prepare_call (jl_typeof_func), {tt});
823
- }
824
-
825
- static jl_cgval_t emit_typeof (jl_codectx_t &ctx, const jl_cgval_t &p)
819
+ static jl_cgval_t emit_typeof (jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull)
826
820
{
827
821
// given p, compute its type
828
822
if (p.constant )
@@ -835,7 +829,7 @@ static jl_cgval_t emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p)
835
829
return mark_julia_const (ctx, jl_typeof (tp));
836
830
}
837
831
}
838
- return mark_julia_type (ctx, emit_typeof (ctx, p.V ), true , jl_datatype_type);
832
+ return mark_julia_type (ctx, emit_typeof (ctx, p.V , maybenull ), true , jl_datatype_type);
839
833
}
840
834
if (p.TIndex ) {
841
835
Value *tindex = ctx.builder .CreateAnd (p.TIndex , ConstantInt::get (getInt8Ty (ctx.builder .getContext ()), 0x7f ));
@@ -870,7 +864,7 @@ static jl_cgval_t emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p)
870
864
BasicBlock *mergeBB = BasicBlock::Create (ctx.builder .getContext (), " merge" , ctx.f );
871
865
ctx.builder .CreateCondBr (isnull, boxBB, unboxBB);
872
866
ctx.builder .SetInsertPoint (boxBB);
873
- auto boxTy = emit_typeof (ctx, p.Vboxed );
867
+ auto boxTy = emit_typeof (ctx, p.Vboxed , maybenull );
874
868
ctx.builder .CreateBr (mergeBB);
875
869
boxBB = ctx.builder .GetInsertBlock (); // could have changed
876
870
ctx.builder .SetInsertPoint (unboxBB);
@@ -892,9 +886,9 @@ static jl_cgval_t emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p)
892
886
}
893
887
894
888
// Returns ctx.types().T_prjlvalue
895
- static Value *emit_typeof_boxed (jl_codectx_t &ctx, const jl_cgval_t &p)
889
+ static Value *emit_typeof_boxed (jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull )
896
890
{
897
- return boxed (ctx, emit_typeof (ctx, p));
891
+ return boxed (ctx, emit_typeof (ctx, p, maybenull ));
898
892
}
899
893
900
894
static Value *emit_datatype_types (jl_codectx_t &ctx, Value *dt)
@@ -1129,6 +1123,23 @@ static Value *emit_nullcheck_guard2(jl_codectx_t &ctx, Value *nullcheck1,
1129
1123
});
1130
1124
}
1131
1125
1126
+ // Returns typeof(v), or null if v is a null pointer at run time and maybenull is true.
1127
+ // This is used when the value might have come from an undefined value (a PhiNode),
1128
+ // yet we try to read its type to compute a union index when moving the value (a PiNode).
1129
+ // Returns a ctx.types().T_prjlvalue typed Value
1130
+ static Value *emit_typeof (jl_codectx_t &ctx, Value *v, bool maybenull)
1131
+ {
1132
+ assert (v != NULL && !isa<AllocaInst>(v) && " expected a conditionally boxed value" );
1133
+ Function *typeof = prepare_call (jl_typeof_func);
1134
+ if (maybenull)
1135
+ return emit_guarded_test (ctx, null_pointer_cmp (ctx, v), Constant::getNullValue (typeof ->getReturnType ()), [&] {
1136
+ // e.g. emit_typeof(ctx, v)
1137
+ return ctx.builder .CreateCall (typeof , {v});
1138
+ });
1139
+ return ctx.builder .CreateCall (typeof , {v});
1140
+ }
1141
+
1142
+
1132
1143
static void emit_type_error (jl_codectx_t &ctx, const jl_cgval_t &x, Value *type, const std::string &msg)
1133
1144
{
1134
1145
Value *msg_val = stringConstPtr (ctx.emission_context , ctx.builder , msg);
@@ -1256,7 +1267,7 @@ static std::pair<Value*, bool> emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x,
1256
1267
BasicBlock *postBB = BasicBlock::Create (ctx.builder .getContext (), " post_isa" , ctx.f );
1257
1268
ctx.builder .CreateCondBr (isboxed, isaBB, postBB);
1258
1269
ctx.builder .SetInsertPoint (isaBB);
1259
- Value *istype_boxed = ctx.builder .CreateICmpEQ (emit_typeof (ctx, x.Vboxed ),
1270
+ Value *istype_boxed = ctx.builder .CreateICmpEQ (emit_typeof (ctx, x.Vboxed , false ),
1260
1271
track_pjlvalue (ctx, literal_pointer_val (ctx, intersected_type)));
1261
1272
ctx.builder .CreateBr (postBB);
1262
1273
isaBB = ctx.builder .GetInsertBlock (); // could have changed
@@ -1312,6 +1323,20 @@ static std::pair<Value*, bool> emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x,
1312
1323
ConstantInt::get (getInt32Ty (ctx.builder .getContext ()), 0 )), false );
1313
1324
}
1314
1325
1326
+ // If this might have been sourced from a PhiNode object, it is possible our
1327
+ // Vboxed pointer itself is null (undef) at runtime even if we thought we should
1328
+ // know exactly the type of the bytes that should have been inside.
1329
+ //
1330
+ // n.b. It is also possible the value is a ghost of some sort, and we will
1331
+ // declare that the pointer is legal (for zero bytes) even though it might be undef.
1332
+ static Value *emit_isa_and_defined (jl_codectx_t &ctx, const jl_cgval_t &val, jl_value_t *typ)
1333
+ {
1334
+ return emit_nullcheck_guard (ctx, val.ispointer () ? val.V : nullptr , [&] {
1335
+ return emit_isa (ctx, val, typ, nullptr ).first ;
1336
+ });
1337
+ }
1338
+
1339
+
1315
1340
static void emit_typecheck (jl_codectx_t &ctx, const jl_cgval_t &x, jl_value_t *type, const std::string &msg)
1316
1341
{
1317
1342
Value *istype;
@@ -2885,42 +2910,16 @@ static Value *compute_box_tindex(jl_codectx_t &ctx, Value *datatype, jl_value_t
2885
2910
return tindex;
2886
2911
}
2887
2912
2888
- // Returns typeof(v), or null if v is a null pointer at run time.
2889
- // This is used when the value might have come from an undefined variable,
2890
- // yet we try to read its type to compute a union index when moving the value.
2891
- static Value *emit_typeof_or_null (jl_codectx_t &ctx, Value *v)
2892
- {
2893
- BasicBlock *nonnull = BasicBlock::Create (ctx.builder .getContext (), " nonnull" , ctx.f );
2894
- BasicBlock *postBB = BasicBlock::Create (ctx.builder .getContext (), " postnull" , ctx.f );
2895
- Value *isnull = ctx.builder .CreateICmpEQ (v, Constant::getNullValue (v->getType ()));
2896
- ctx.builder .CreateCondBr (isnull, postBB, nonnull);
2897
- BasicBlock *entry = ctx.builder .GetInsertBlock ();
2898
- ctx.builder .SetInsertPoint (nonnull);
2899
- Value *typof = emit_typeof (ctx, v);
2900
- ctx.builder .CreateBr (postBB);
2901
- nonnull = ctx.builder .GetInsertBlock (); // could have changed
2902
- ctx.builder .SetInsertPoint (postBB);
2903
- PHINode *ti = ctx.builder .CreatePHI (typof->getType (), 2 );
2904
- ti->addIncoming (Constant::getNullValue (typof->getType ()), entry);
2905
- ti->addIncoming (typof, nonnull);
2906
- return ti;
2907
- }
2908
-
2909
2913
// get the runtime tindex value, assuming val is already converted to type typ if it has a TIndex
2910
- static Value *compute_tindex_unboxed (jl_codectx_t &ctx, const jl_cgval_t &val, jl_value_t *typ)
2914
+ static Value *compute_tindex_unboxed (jl_codectx_t &ctx, const jl_cgval_t &val, jl_value_t *typ, bool maybenull= false )
2911
2915
{
2912
2916
if (val.typ == jl_bottom_type)
2913
2917
return UndefValue::get (getInt8Ty (ctx.builder .getContext ()));
2914
2918
if (val.constant )
2915
2919
return ConstantInt::get (getInt8Ty (ctx.builder .getContext ()), get_box_tindex ((jl_datatype_t *)jl_typeof (val.constant ), typ));
2916
-
2917
2920
if (val.TIndex )
2918
2921
return ctx.builder .CreateAnd (val.TIndex , ConstantInt::get (getInt8Ty (ctx.builder .getContext ()), 0x7f ));
2919
- Value *typof;
2920
- if (val.isboxed && !jl_is_concrete_type (val.typ ) && !jl_is_type_type (val.typ ))
2921
- typof = emit_typeof_or_null (ctx, val.V );
2922
- else
2923
- typof = emit_typeof_boxed (ctx, val);
2922
+ Value *typof = emit_typeof_boxed (ctx, val, maybenull);
2924
2923
return compute_box_tindex (ctx, typof, val.typ , typ);
2925
2924
}
2926
2925
@@ -3102,14 +3101,17 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con
3102
3101
Value *src_ptr = data_pointer (ctx, src);
3103
3102
unsigned nb = jl_datatype_size (typ);
3104
3103
unsigned alignment = julia_alignment (typ);
3105
- Value *nbytes = ConstantInt::get (getSizeTy (ctx.builder .getContext ()), nb);
3106
- if (skip) {
3107
- // TODO: this Select is very bad for performance, but is necessary to work around LLVM bugs with the undef option that we want to use:
3108
- // select copy dest -> dest to simulate an undef value / conditional copy
3109
- // src_ptr = ctx.builder.CreateSelect(skip, dest, src_ptr);
3110
- nbytes = ctx.builder .CreateSelect (skip, Constant::getNullValue (getSizeTy (ctx.builder .getContext ())), nbytes);
3111
- }
3112
- emit_memcpy (ctx, dest, tbaa_dst, src_ptr, src.tbaa , nbytes, alignment, isVolatile);
3104
+ // TODO: this branch may be bad for performance, but is necessary to work around LLVM bugs with the undef option that we want to use:
3105
+ // select copy dest -> dest to simulate an undef value / conditional copy
3106
+ // if (skip) src_ptr = ctx.builder.CreateSelect(skip, dest, src_ptr);
3107
+ auto f = [&] {
3108
+ (void )emit_memcpy (ctx, dest, tbaa_dst, src_ptr, src.tbaa , nb, alignment, isVolatile);
3109
+ return nullptr ;
3110
+ };
3111
+ if (skip)
3112
+ emit_guarded_test (ctx, skip, nullptr , f);
3113
+ else
3114
+ f ();
3113
3115
}
3114
3116
}
3115
3117
}
@@ -3162,12 +3164,16 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con
3162
3164
}
3163
3165
else {
3164
3166
assert (src.isboxed && " expected boxed value for sizeof/alignment computation" );
3165
- Value *datatype = emit_typeof_boxed (ctx, src);
3166
- Value *copy_bytes = emit_datatype_size (ctx, datatype);
3167
- if (skip) {
3168
- copy_bytes = ctx.builder .CreateSelect (skip, ConstantInt::get (copy_bytes->getType (), 0 ), copy_bytes);
3169
- }
3170
- emit_memcpy (ctx, dest, tbaa_dst, src, copy_bytes, /* TODO: min-align*/ 1 , isVolatile);
3167
+ auto f = [&] {
3168
+ Value *datatype = emit_typeof_boxed (ctx, src);
3169
+ Value *copy_bytes = emit_datatype_size (ctx, datatype);
3170
+ emit_memcpy (ctx, dest, tbaa_dst, src, copy_bytes, /* TODO: min-align*/ 1 , isVolatile);
3171
+ return nullptr ;
3172
+ };
3173
+ if (skip)
3174
+ emit_guarded_test (ctx, skip, nullptr , f);
3175
+ else
3176
+ f ();
3171
3177
}
3172
3178
}
3173
3179
0 commit comments