Skip to content

Commit 3e82aba

Browse files
committed
[WIP] allocation complement to #55045
1 parent b1b968e commit 3e82aba

File tree

6 files changed

+139
-60
lines changed

6 files changed

+139
-60
lines changed

base/reflection.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ struct FieldDescStorage{T}
642642
offset::T
643643
end
644644
FieldDesc(fd::FieldDescStorage{T}) where {T} =
645-
FieldDesc(false, fd.ptrsize & 1 != 0,
645+
FieldDesc(false, (fd.ptrsize & 3) == 1,
646646
fd.ptrsize >> 1, fd.offset)
647647

648648
struct DataTypeFieldDesc

src/builtins.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,23 +85,28 @@ static int NOINLINE compare_fields(const jl_value_t *a, const jl_value_t *b, jl_
8585
size_t offs = jl_field_offset(dt, f);
8686
char *ao = (char*)a + offs;
8787
char *bo = (char*)b + offs;
88-
if (jl_field_isptr(dt, f)) {
88+
enum jl_fieldkind_t kind = jl_field_kind(dt, i);
89+
if (kind == JL_FIELDKIND_ISPTR) {
8990
// Save ptr recursion until the end -- only recurse if otherwise equal
9091
// Note that we also skip comparing the pointers for null here, because
9192
// null fields are rare so it can save CPU to delay this read too.
9293
continue;
9394
}
9495
else {
9596
jl_datatype_t *ft = (jl_datatype_t*)jl_field_type_concrete(dt, f);
96-
if (jl_is_uniontype(ft)) {
97+
if (kind == JL_FIELDKIND_UNION) {
98+
assert(jl_is_uniontype(ft));
9799
size_t idx = jl_field_size(dt, f) - 1;
98100
uint8_t asel = ((uint8_t*)ao)[idx];
99101
uint8_t bsel = ((uint8_t*)bo)[idx];
100102
if (asel != bsel)
101103
return 0;
102104
ft = (jl_datatype_t*)jl_nth_union_component((jl_value_t*)ft, asel);
103105
}
104-
else if (ft->layout->first_ptr >= 0) {
106+
else if (kind != JL_FIELDKIND_ISBITS) {
107+
if (jl_is_uniontype(ft))
108+
ft = (jl_datatype_t*)((jl_uniontype_t*)ft)->b;
109+
assert(ft->layout->first_ptr >= 0);
105110
// If the field is a inline immutable that can be undef
106111
// we need to check for undef first since undef struct
107112
// may have fields that are different but should still be treated as equal.
@@ -408,19 +413,25 @@ static uintptr_t immut_id_(jl_datatype_t *dt, jl_value_t *v, uintptr_t h) JL_NOT
408413
size_t offs = jl_field_offset(dt, f);
409414
char *vo = (char*)v + offs;
410415
uintptr_t u;
411-
if (jl_field_isptr(dt, f)) {
416+
enum jl_fieldkind_t kind = jl_field_kind(dt, f);
417+
if (kind == JL_FIELDKIND_ISPTR) {
412418
jl_value_t *f = *(jl_value_t**)vo;
413419
u = (f == NULL) ? 0 : jl_object_id(f);
414420
}
415421
else {
416422
jl_datatype_t *fieldtype = (jl_datatype_t*)jl_field_type_concrete(dt, f);
417-
if (jl_is_uniontype(fieldtype)) {
423+
if (kind == JL_FIELDKIND_ISUNION) {
424+
assert(jl_is_uniontype(fieldtype));
418425
uint8_t sel = ((uint8_t*)vo)[jl_field_size(dt, f) - 1];
419426
fieldtype = (jl_datatype_t*)jl_nth_union_component((jl_value_t*)fieldtype, sel);
420427
}
428+
else if (kind != JL_FIELDKIND_ISBITS) {
429+
if (jl_is_uniontype(fieldtype))
430+
fieldtype = (jl_datatype_t*)((jl_uniontype_t*)fieldtype)->b;
431+
assert(fieldtype->layout->first_ptr >= 0);
432+
}
421433
assert(jl_is_datatype(fieldtype) && !fieldtype->name->abstract && !fieldtype->name->mutabl);
422-
int32_t first_ptr = fieldtype->layout->first_ptr;
423-
if (first_ptr >= 0 && ((jl_value_t**)vo)[first_ptr] == NULL) {
434+
if (kind == JL_FIELDKIND_OTHER && ((jl_value_t**)vo)[fieldtype->layout->first_ptr] == NULL) {
424435
// If the field is a inline immutable that can be can be undef
425436
// we need to check to check for undef first since undef struct
426437
// may have fields that are different but should still be treated as equal.

src/cgutils.cpp

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -788,11 +788,12 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, LLVMContext &ctxt,
788788
abort();
789789
}
790790
Type *lty;
791-
if (jl_field_isptr(jst, i)) {
791+
enum jl_fieldkind_t kind = jl_field_kind(jst, i);
792+
if (kind == JL_FIELDKIND_ISPTR) {
792793
lty = JuliaType::get_prjlvalue_ty(ctxt);
793794
isvector = false;
794795
}
795-
else if (jl_is_uniontype(ty)) {
796+
else if (kind == JL_FIELDKIND_ISUNION) {
796797
// pick an Integer type size such that alignment will generally be correct,
797798
// and always end with an Int8 (selector byte).
798799
// We may need to insert padding first to get to the right offset
@@ -822,6 +823,8 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, LLVMContext &ctxt,
822823
continue;
823824
}
824825
else {
826+
if (kind == JL_FIELDKIND_ISOTHER && jl_is_uniontype(ty))
827+
ty = ((jl_uniontype_t*)ty)->b;
825828
bool isptr;
826829
lty = _julia_struct_to_llvm(ctx, ctxt, ty, &isptr, llvmcall);
827830
assert(lty && !isptr);
@@ -1943,11 +1946,19 @@ static void emit_lockstate_value(jl_codectx_t &ctx, Value *strct, bool newstate)
19431946

19441947
// If `nullcheck` is not NULL and a pointer NULL check is necessary
19451948
// store the pointer to be checked in `*nullcheck` instead of checking it
1946-
static jl_cgval_t typed_load(jl_codectx_t &ctx, Value *ptr, Value *idx_0based, jl_value_t *jltype,
1949+
static jl_cgval_t typed_load(jl_codectx_t &ctx, Value *ptr, Value *idx_0based, jl_value_t *loadtype,
19471950
MDNode *tbaa, MDNode *aliasscope, bool isboxed, AtomicOrdering Order,
19481951
bool maybe_null_if_boxed = true, unsigned alignment = 0,
19491952
Value **nullcheck = nullptr)
19501953
{
1954+
jl_value_t *jltype = loadtype;
1955+
Value *otherval = nullptr;
1956+
bool isother = !isboxed && jl_is_uniontype(jltype);
1957+
if (isother) {
1958+
nullcheck = &otherval;
1959+
maybe_null = true;
1960+
jltype = ((jl_uniontype_t*)jltype)->b;
1961+
}
19511962
// TODO: we should use unordered loads for anything with CountTrackedPointers(elty).count > 0 (if not otherwise locked)
19521963
Type *elty = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, jltype);
19531964
if (type_is_ghost(elty)) {
@@ -2042,10 +2053,16 @@ static jl_cgval_t typed_load(jl_codectx_t &ctx, Value *ptr, Value *idx_0based, j
20422053
instr = ctx.builder.CreateLoad(intcast->getAllocatedType(), intcast);
20432054
instr = ctx.builder.CreateTrunc(instr, getInt1Ty(ctx.builder.getContext()));
20442055
}
2056+
Value *tindex = nullptr;
2057+
if (isother) {
2058+
tindex = ctx.builder.CreateZExt(null_pointer_cmp(ctx, otherval), getInt8Ty(ctx.builder.getContext()));
2059+
assert(ret.Vboxed == nullptr);
2060+
ret = jl_cgval_t(ret, jl_field_type(jt, idx), tindex);
2061+
}
20452062
if (instr)
2046-
return mark_julia_type(ctx, instr, isboxed, jltype);
2063+
return mark_julia_type(ctx, instr, isboxed, loadtype);
20472064
else
2048-
return mark_julia_slot(intcast, jltype, NULL, ctx.tbaa().tbaa_stack);
2065+
return mark_julia_slot(intcast, loadtype, tindex, ctx.tbaa().tbaa_stack);
20492066
}
20502067

20512068
static jl_cgval_t typed_store(jl_codectx_t &ctx,
@@ -2495,7 +2512,8 @@ static bool field_may_be_null(const jl_cgval_t &strct, jl_datatype_t *stt, size_
24952512
size_t nfields = jl_datatype_nfields(stt);
24962513
if (idx < nfields - (unsigned)stt->name->n_uninitialized)
24972514
return false;
2498-
if (!jl_field_isptr(stt, idx) && !jl_type_hasptr(jl_field_type(stt, idx)))
2515+
enum jl_fieldkind_t kind = jl_field_kind(stt, idx);
2516+
if (kind == JL_FIELDKIND_ISUNION || kind == JL_FIELDKIND_ISBITS)
24992517
return false;
25002518
if (strct.constant) {
25012519
if ((jl_is_immutable(stt) || jl_field_isconst(stt, idx)) && jl_field_isdefined(strct.constant, idx))
@@ -2839,7 +2857,8 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st
28392857
if (type_is_ghost(julia_type_to_llvm(ctx, jfty)))
28402858
return ghostValue(ctx, jfty);
28412859
Value *needlock = nullptr;
2842-
if (isatomic && !jl_field_isptr(jt, idx) && jl_datatype_size(jfty) > MAX_ATOMIC_SIZE) {
2860+
enum jl_fieldkind_t kind = jl_field_kind(jt, idx);
2861+
if (isatomic && kind != JL_FIELDKIND_ISPTR && jl_datatype_size(jfty) > MAX_ATOMIC_SIZE) {
28432862
assert(strct.isboxed);
28442863
needlock = boxed(ctx, strct);
28452864
}
@@ -2876,7 +2895,7 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st
28762895
setNameWithField(ctx.emission_context, addr, get_objname, jt, idx, Twine("_ptr"));
28772896
}
28782897
}
2879-
if (jl_field_isptr(jt, idx)) {
2898+
if (kind == JL_FIELDKIND_ISPTR) {
28802899
setNameWithField(ctx.emission_context, addr, get_objname, jt, idx, Twine("_ptr"));
28812900
LoadInst *Load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, addr, Align(sizeof(void*)));
28822901
setNameWithField(ctx.emission_context, Load, get_objname, jt, idx, Twine());
@@ -2888,7 +2907,8 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st
28882907
null_pointer_check(ctx, fldv, nullcheck);
28892908
return mark_julia_type(ctx, fldv, true, jfty);
28902909
}
2891-
else if (jl_is_uniontype(jfty)) {
2910+
else if (kind == JL_FIELDKIND_ISUNION) {
2911+
assert(jl_is_uniontype(jfty));
28922912
size_t fsz = 0, al = 0;
28932913
int union_max = jl_islayout_inline(jfty, &fsz, &al);
28942914
bool isptr = (union_max == 0);
@@ -2908,11 +2928,13 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st
29082928
}
29092929
return val;
29102930
}
2911-
assert(jl_is_concrete_type(jfty));
2912-
if (jl_field_isconst(jt, idx) && !(maybe_null && (jfty == (jl_value_t*)jl_bool_type ||
2913-
((jl_datatype_t*)jfty)->layout->npointers))) {
2914-
// just compute the pointer and let user load it when necessary
2915-
return mark_julia_slot(addr, jfty, NULL, tbaa);
2931+
if (kind != JL_FIELDKIND_ISOTHER) {
2932+
assert(jl_is_concrete_type(jfty));
2933+
if (jl_field_isconst(jt, idx) && !(maybe_null && (jfty == (jl_value_t*)jl_bool_type ||
2934+
((jl_datatype_t*)jfty)->layout->npointers))) {
2935+
// just compute the pointer and let user load it when necessary
2936+
return mark_julia_slot(addr, jfty, NULL, tbaa);
2937+
}
29162938
}
29172939
unsigned align = jl_field_align(jt, idx);
29182940
if (needlock)

src/datatype.c

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -244,17 +244,17 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t sz,
244244
if (fielddesc_type == 0) {
245245
desc8[i].offset = desc[i].offset;
246246
desc8[i].size = desc[i].size;
247-
desc8[i].isptr = desc[i].isptr;
247+
desc8[i].kind = desc[i].kind;
248248
}
249249
else if (fielddesc_type == 1) {
250250
desc16[i].offset = desc[i].offset;
251251
desc16[i].size = desc[i].size;
252-
desc16[i].isptr = desc[i].isptr;
252+
desc16[i].kind = desc[i].kind;
253253
}
254254
else {
255255
desc32[i].offset = desc[i].offset;
256256
desc32[i].size = desc[i].size;
257-
desc32[i].isptr = desc[i].isptr;
257+
desc32[i].kind = desc[i].kind;
258258
}
259259
}
260260
if (first_ptr >= 0) {
@@ -686,23 +686,32 @@ void jl_compute_field_offsets(jl_datatype_t *st)
686686
for (i = 0; i < nfields; i++) {
687687
jl_value_t *fld = jl_field_type(st, i);
688688
int isatomic = jl_field_isatomic(st, i);
689+
jl_value_t *restfld = fld;
690+
if (jl_is_uniontype(fld) && jl_is_datatype_singleton(((jl_uniontype_t*)fld)->a)) {
691+
restfld = ((jl_uniontype_t*)fld)->b;
692+
}
689693
size_t fsz = 0, al = 1;
690-
if (jl_islayout_inline(fld, &fsz, &al) && (!isatomic || jl_is_datatype(fld))) { // aka jl_datatype_isinlinealloc
694+
if (jl_islayout_inline(restfld, &fsz, &al) && (!isatomic || jl_is_datatype(fld))) { // aka jl_datatype_isinlinealloc
691695
if (__unlikely(fsz > max_size))
692696
// Should never happen
693697
throw_ovf(should_malloc, desc, st, fsz);
694-
desc[i].isptr = 0;
695-
if (jl_is_uniontype(fld)) {
698+
if (!jl_is_datatype(restfld) || (restfld != fld && jl_islayout_inline(fld, &fsz, &al)))
699+
desc[i].kind = JL_FIELDKIND_ISUNION;
700+
else if (((jl_datatype_t*)restfld)->layout->first_ptr >= 0)
701+
desc[i].kind = JL_FIELDKIND_ISOTHER;
702+
else
703+
desc[i].kind = JL_FIELDKIND_ISBITS;
704+
if (desc[i].kind == JL_FIELDKIND_ISUNION) {
696705
fsz += 1; // selector byte
697706
zeroinit = 1;
698707
// TODO: Some unions could be bits comparable.
699708
isbitsegal = 0;
700709
}
701710
else {
702-
uint32_t fld_npointers = ((jl_datatype_t*)fld)->layout->npointers;
703-
if (((jl_datatype_t*)fld)->layout->flags.haspadding)
711+
uint32_t fld_npointers = ((jl_datatype_t*)restfld)->layout->npointers;
712+
if (((jl_datatype_t*)restfld)->layout->flags.haspadding)
704713
haspadding = 1;
705-
if (!((jl_datatype_t*)fld)->layout->flags.isbitsegal)
714+
if (!((jl_datatype_t*)restfld)->layout->flags.isbitsegal)
706715
isbitsegal = 0;
707716
if (i >= nfields - st->name->n_uninitialized && fld_npointers &&
708717
fld_npointers * sizeof(void*) != fsz) {
@@ -719,7 +728,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
719728
isbitsegal = 0;
720729
}
721730
if (!zeroinit)
722-
zeroinit = ((jl_datatype_t*)fld)->zeroinit;
731+
zeroinit = ((jl_datatype_t*)restfld)->zeroinit;
723732
npointers += fld_npointers;
724733
}
725734
}
@@ -728,7 +737,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
728737
if (fsz > MAX_ALIGN)
729738
fsz = MAX_ALIGN;
730739
al = fsz;
731-
desc[i].isptr = 1;
740+
desc[i].kind = JL_FIELDKIND_ISPTR;
732741
zeroinit = 1;
733742
npointers++;
734743
if (!jl_pointer_egal(fld)) {
@@ -783,9 +792,12 @@ void jl_compute_field_offsets(jl_datatype_t *st)
783792
for (i = 0; i < nfields; i++) {
784793
jl_value_t *fld = jl_field_type(st, i);
785794
uint32_t offset = desc[i].offset / sizeof(jl_value_t**);
786-
if (desc[i].isptr)
795+
if (desc[i].kind == JL_FIELDKIND_ISPTR)
787796
pointers[ptr_i++] = offset;
788-
else if (jl_is_datatype(fld)) {
797+
else if (desc[i].kind == JL_FIELDKIND_ISOTHER) {
798+
if (jl_is_uniontype(fld)) {
799+
fld = ((jl_uniontype_t*)fld)->b;
800+
}
789801
int j, npointers = ((jl_datatype_t*)fld)->layout->npointers;
790802
for (j = 0; j < npointers; j++) {
791803
pointers[ptr_i++] = offset + jl_ptr_offset((jl_datatype_t*)fld, j);
@@ -1755,18 +1767,28 @@ JL_DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i)
17551767
if (i >= jl_datatype_nfields(st))
17561768
jl_bounds_error_int(v, i + 1);
17571769
size_t offs = jl_field_offset(st, i);
1758-
if (jl_field_isptr(st, i)) {
1770+
enum jl_fieldkind_t kind = jl_field_kind(st, i);
1771+
if (kind == JL_FIELDKIND_ISPTR) {
17591772
return jl_atomic_load_relaxed((_Atomic(jl_value_t*)*)((char*)v + offs));
17601773
}
17611774
jl_value_t *ty = jl_field_type_concrete(st, i);
17621775
int isatomic = jl_field_isatomic(st, i);
1763-
if (jl_is_uniontype(ty)) {
1776+
jl_value_t *undefval = NULL;
1777+
if (kind != JL_FIELDKIND_ISBITS) {
17641778
assert(!isatomic);
1765-
size_t fsz = jl_field_size(st, i);
1766-
uint8_t sel = ((uint8_t*)v)[offs + fsz - 1];
1767-
ty = jl_nth_union_component(ty, sel);
1768-
if (jl_is_datatype_singleton((jl_datatype_t*)ty))
1769-
return ((jl_datatype_t*)ty)->instance;
1779+
if (kind == JL_FIELDKIND_ISUNION) {
1780+
size_t fsz = jl_field_size(st, i);
1781+
uint8_t sel = ((uint8_t*)v)[offs + fsz - 1];
1782+
ty = jl_nth_union_component(ty, sel);
1783+
if (jl_is_datatype_singleton((jl_datatype_t*)ty))
1784+
return ((jl_datatype_t*)ty)->instance;
1785+
}
1786+
else { // kind == JL_FIELDKIND_ISOTHER
1787+
assert(jl_is_uniontype(ty));
1788+
jl_uniontype_t *uty = (jl_uniontype_t*)ty;
1789+
undefval = ((jl_datatype_t*)uty->a)->instance;
1790+
ty = uty->b;
1791+
}
17701792
}
17711793
jl_value_t *r;
17721794
size_t fsz = jl_datatype_size(ty);
@@ -1785,7 +1807,9 @@ JL_DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i)
17851807
// TODO: a finalizer here could make the isunion case not quite right
17861808
r = jl_new_bits(ty, (char*)v + offs);
17871809
}
1788-
return undefref_check((jl_datatype_t*)ty, r);
1810+
if (kind != JL_FIELDKIND_ISOTHER)
1811+
return r;
1812+
return undefref_check((jl_datatype_t*)ty, r, undefval);
17891813
}
17901814

17911815
JL_DLLEXPORT jl_value_t *jl_get_nth_field_noalloc(jl_value_t *v JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT
@@ -1812,16 +1836,16 @@ inline void set_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t
18121836
assert(jl_field_isptr(st, i) && *(jl_value_t**)((char*)v + offs) == NULL);
18131837
return;
18141838
}
1815-
if (jl_field_isptr(st, i)) {
1839+
enum jl_fieldkind_t kind = jl_field_kind(st, i);
1840+
if (kind == JL_FIELDKIND_ISPTR) {
18161841
jl_atomic_store_release((_Atomic(jl_value_t*)*)((char*)v + offs), rhs);
18171842
jl_gc_wb(v, rhs);
18181843
}
18191844
else {
18201845
jl_value_t *ty = jl_field_type_concrete(st, i);
18211846
jl_value_t *rty = jl_typeof(rhs);
1822-
int hasptr;
1823-
int isunion = jl_is_uniontype(ty);
1824-
if (isunion) {
1847+
int hasptr = (kind == JL_FIELDKIND_ISOTHER);
1848+
if (kind == JL_FIELDKIND_ISUNION) {
18251849
assert(!isatomic);
18261850
size_t fsz = jl_field_size(st, i);
18271851
uint8_t *psel = &((uint8_t*)v)[offs + fsz - 1];
@@ -1831,10 +1855,19 @@ inline void set_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t
18311855
*psel = nth;
18321856
if (jl_is_datatype_singleton((jl_datatype_t*)rty))
18331857
return;
1834-
hasptr = 0;
18351858
}
18361859
else {
1837-
hasptr = ((jl_datatype_t*)ty)->layout->first_ptr >= 0;
1860+
if (hasptr && jl_is_uniontype(ty)) {
1861+
jl_uniontype_t *uty = (jl_uniontype_t*)ty;
1862+
jl_value_t *undefval = ((jl_datatype_t*)uty->a)->instance;
1863+
ty = uty->b;
1864+
assert(((jl_datatype_t*)ty)->layout->first_ptr >= 0);
1865+
if (undefval == rhs) {
1866+
jl_atomic_store_relaxed((_Atomic(jl_value_t*)*)((char*)v + offs) + ((jl_datatype_t*)ty)->layout->first_ptr, NULL);
1867+
return;
1868+
}
1869+
}
1870+
assert(hasptr == (((jl_datatype_t*)ty)->layout->first_ptr >= 0));
18381871
}
18391872
size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
18401873
assert(!isatomic || jl_typeis(rhs, ty));
@@ -2235,9 +2268,9 @@ JL_DLLEXPORT int jl_field_isdefined(jl_value_t *v, size_t i) JL_NOTSAFEPOINT
22352268
jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
22362269
size_t offs = jl_field_offset(st, i);
22372270
_Atomic(jl_value_t*) *fld = (_Atomic(jl_value_t*)*)((char*)v + offs);
2238-
if (!jl_field_isptr(st, i)) {
2239-
jl_datatype_t *ft = (jl_datatype_t*)jl_field_type_concrete(st, i);
2240-
if (!jl_is_datatype(ft) || ft->layout->first_ptr < 0)
2271+
enum jl_fieldkind_t kind = jl_field_kind(st, i);
2272+
if (kind != JL_FIELDKIND_ISPTR) {
2273+
if (kind != JL_FIELDKIND_ISOTHER || jl_is_uniontype(jl_field_type_concrete(st, i)))
22412274
return 2; // isbits are always defined
22422275
fld += ft->layout->first_ptr;
22432276
}

0 commit comments

Comments
 (0)