@@ -765,6 +765,12 @@ static bool for_each_uniontype_small(
765
765
return false ;
766
766
}
767
767
768
+ static bool is_uniontype_allunboxed (jl_value_t *typ)
769
+ {
770
+ unsigned counter = 0 ;
771
+ return for_each_uniontype_small ([&](unsigned , jl_datatype_t *) {}, typ, counter);
772
+ }
773
+
768
774
static Value *emit_typeof_boxed (jl_codectx_t &ctx, const jl_cgval_t &p);
769
775
770
776
static unsigned get_box_tindex (jl_datatype_t *jt, jl_value_t *ut)
@@ -841,13 +847,9 @@ static jl_cgval_t emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p)
841
847
}
842
848
if (p.TIndex ) {
843
849
Value *tindex = ctx.builder .CreateAnd (p.TIndex , ConstantInt::get (T_int8, 0x7f ));
844
- unsigned counter = 0 ;
845
- bool allunboxed = for_each_uniontype_small (
846
- [&](unsigned idx, jl_datatype_t *jt) { },
847
- p.typ ,
848
- counter);
850
+ bool allunboxed = is_uniontype_allunboxed (p.typ );
849
851
Value *datatype_or_p = imaging_mode ? Constant::getNullValue (T_ppjlvalue) : V_rnull;
850
- counter = 0 ;
852
+ unsigned counter = 0 ;
851
853
for_each_uniontype_small (
852
854
[&](unsigned idx, jl_datatype_t *jt) {
853
855
Value *cmp = ctx.builder .CreateICmpEQ (tindex, ConstantInt::get (T_int8, idx));
@@ -1064,10 +1066,20 @@ static void raise_exception_unless(jl_codectx_t &ctx, Value *cond, Value *exc)
1064
1066
raise_exception (ctx, exc, passBB);
1065
1067
}
1066
1068
1067
- static void null_pointer_check (jl_codectx_t &ctx, Value *v)
1069
+ static Value * null_pointer_cmp (jl_codectx_t &ctx, Value *v)
1068
1070
{
1069
- raise_exception_unless (ctx,
1070
- ctx.builder .CreateICmpNE (v, Constant::getNullValue (v->getType ())),
1071
+ return ctx.builder .CreateICmpNE (v, Constant::getNullValue (v->getType ()));
1072
+ }
1073
+
1074
+ // If `nullcheck` is not NULL and a pointer NULL check is necessary
1075
+ // store the pointer to be checked in `*nullcheck` instead of checking it
1076
+ static void null_pointer_check (jl_codectx_t &ctx, Value *v, Value **nullcheck = nullptr )
1077
+ {
1078
+ if (nullcheck) {
1079
+ *nullcheck = v;
1080
+ return ;
1081
+ }
1082
+ raise_exception_unless (ctx, null_pointer_cmp (ctx, v),
1071
1083
literal_pointer_val (ctx, jl_undefref_exception));
1072
1084
}
1073
1085
@@ -1378,9 +1390,12 @@ Value *extract_first_ptr(jl_codectx_t &ctx, Value *V)
1378
1390
return ctx.builder .CreateExtractValue (V, path);
1379
1391
}
1380
1392
1393
+ // If `nullcheck` is not NULL and a pointer NULL check is necessary
1394
+ // store the pointer to be checked in `*nullcheck` instead of checking it
1381
1395
static jl_cgval_t typed_load (jl_codectx_t &ctx, Value *ptr, Value *idx_0based, jl_value_t *jltype,
1382
1396
MDNode *tbaa, MDNode *aliasscope,
1383
- bool maybe_null_if_boxed = true , unsigned alignment = 0 )
1397
+ bool maybe_null_if_boxed = true , unsigned alignment = 0 ,
1398
+ Value **nullcheck = nullptr )
1384
1399
{
1385
1400
bool isboxed;
1386
1401
Type *elty = julia_type_to_llvm (ctx, jltype, &isboxed);
@@ -1416,7 +1431,7 @@ static jl_cgval_t typed_load(jl_codectx_t &ctx, Value *ptr, Value *idx_0based, j
1416
1431
if (maybe_null_if_boxed) {
1417
1432
Value *first_ptr = isboxed ? load : extract_first_ptr (ctx, load);
1418
1433
if (first_ptr)
1419
- null_pointer_check (ctx, first_ptr);
1434
+ null_pointer_check (ctx, first_ptr, nullcheck );
1420
1435
}
1421
1436
// }
1422
1437
if (jltype == (jl_value_t *)jl_bool_type) { // "freeze" undef memory to a valid value
@@ -1580,7 +1595,9 @@ static void emit_memcpy(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, const j
1580
1595
1581
1596
1582
1597
1583
- static jl_cgval_t emit_getfield_knownidx (jl_codectx_t &ctx, const jl_cgval_t &strct, unsigned idx, jl_datatype_t *jt);
1598
+ static jl_cgval_t emit_getfield_knownidx (jl_codectx_t &ctx, const jl_cgval_t &strct,
1599
+ unsigned idx, jl_datatype_t *jt,
1600
+ Value **nullcheck = nullptr );
1584
1601
1585
1602
static bool emit_getfield_unknownidx (jl_codectx_t &ctx,
1586
1603
jl_cgval_t *ret, jl_cgval_t strct,
@@ -1711,7 +1728,11 @@ static bool emit_getfield_unknownidx(jl_codectx_t &ctx,
1711
1728
return false ;
1712
1729
}
1713
1730
1714
- static jl_cgval_t emit_getfield_knownidx (jl_codectx_t &ctx, const jl_cgval_t &strct, unsigned idx, jl_datatype_t *jt)
1731
+ // If `nullcheck` is not NULL and a pointer NULL check is necessary
1732
+ // store the pointer to be checked in `*nullcheck` instead of checking it
1733
+ static jl_cgval_t emit_getfield_knownidx (jl_codectx_t &ctx, const jl_cgval_t &strct,
1734
+ unsigned idx, jl_datatype_t *jt,
1735
+ Value **nullcheck)
1715
1736
{
1716
1737
jl_value_t *jfty = jl_field_type (jt, idx);
1717
1738
if (jfty == jl_bottom_type) {
@@ -1759,7 +1780,7 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st
1759
1780
maybe_mark_load_dereferenceable (Load, maybe_null, jl_field_type (jt, idx));
1760
1781
Value *fldv = tbaa_decorate (tbaa, Load);
1761
1782
if (maybe_null)
1762
- null_pointer_check (ctx, fldv);
1783
+ null_pointer_check (ctx, fldv, nullcheck );
1763
1784
return mark_julia_type (ctx, fldv, true , jfty);
1764
1785
}
1765
1786
else if (jl_is_uniontype (jfty)) {
@@ -1796,7 +1817,7 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st
1796
1817
return mark_julia_slot (addr, jfty, NULL , tbaa);
1797
1818
}
1798
1819
unsigned align = jl_field_align (jt, idx);
1799
- return typed_load (ctx, addr, NULL , jfty, tbaa, nullptr , maybe_null, align);
1820
+ return typed_load (ctx, addr, NULL , jfty, tbaa, nullptr , maybe_null, align, nullcheck );
1800
1821
}
1801
1822
else if (isa<UndefValue>(strct.V )) {
1802
1823
return jl_cgval_t ();
@@ -1858,7 +1879,7 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st
1858
1879
if (maybe_null) {
1859
1880
Value *first_ptr = jl_field_isptr (jt, idx) ? fldv : extract_first_ptr (ctx, fldv);
1860
1881
if (first_ptr)
1861
- null_pointer_check (ctx, first_ptr);
1882
+ null_pointer_check (ctx, first_ptr, nullcheck );
1862
1883
}
1863
1884
return mark_julia_type (ctx, fldv, jl_field_isptr (jt, idx), jfty);
1864
1885
}
0 commit comments