@@ -1110,6 +1110,18 @@ static const auto jlgetnthfieldchecked_func = new JuliaFunction<TypeFnContextAnd
1110
1110
Attributes(C, {Attribute::NonNull}),
1111
1111
None); },
1112
1112
};
1113
+ static const auto jlfieldindex_func = new JuliaFunction<>{
1114
+ XSTR(jl_field_index),
1115
+ [](LLVMContext &C) {
1116
+ auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
1117
+ return FunctionType::get(getInt32Ty(C),
1118
+ {T_prjlvalue, T_prjlvalue, getInt32Ty(C)}, false);
1119
+ },
1120
+ [](LLVMContext &C) { return AttributeList::get(C,
1121
+ Attributes(C, {Attribute::NoUnwind, Attribute::ReadOnly, Attribute::WillReturn}),
1122
+ AttributeSet(),
1123
+ None); }, // This function can error if the third argument is 1 so don't do that.
1124
+ };
1113
1125
static const auto jlfieldisdefinedchecked_func = new JuliaFunction<TypeFnContextAndSizeT>{
1114
1126
XSTR(jl_field_isdefined_checked),
1115
1127
[](LLVMContext &C, Type *T_size) {
@@ -3841,9 +3853,9 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3841
3853
return true;
3842
3854
}
3843
3855
}
3844
- else if (fld.typ == (jl_value_t*)jl_symbol_type) {
3845
- if (jl_is_datatype(utt) && !jl_is_namedtuple_type (utt)) { // TODO: Look into this for NamedTuple
3846
- if (jl_struct_try_layout(utt) && ( jl_datatype_nfields(utt) == 1)) {
3856
+ else if (fld.typ == (jl_value_t*)jl_symbol_type) { // Known type but unknown symbol
3857
+ if (jl_is_datatype(utt) && (utt != jl_module_type) && jl_struct_try_layout(utt)) {
3858
+ if (( jl_datatype_nfields(utt) == 1 && !jl_is_namedtuple_type(utt) )) {
3847
3859
jl_svec_t *fn = jl_field_names(utt);
3848
3860
assert(jl_svec_len(fn) == 1);
3849
3861
Value *typ_sym = literal_pointer_val(ctx, jl_svecref(fn, 0));
@@ -3852,9 +3864,17 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3852
3864
*ret = emit_getfield_knownidx(ctx, obj, 0, utt, order);
3853
3865
return true;
3854
3866
}
3867
+ else {
3868
+ Value *index = ctx.builder.CreateCall(prepare_call(jlfieldindex_func),
3869
+ {emit_typeof(ctx, obj, false, false), boxed(ctx, fld), ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0)});
3870
+ Value *cond = ctx.builder.CreateICmpNE(index, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), -1));
3871
+ emit_hasnofield_error_ifnot(ctx, cond, utt->name->name, fld);
3872
+ Value *idx2 = ctx.builder.CreateAdd(ctx.builder.CreateIntCast(index, ctx.types().T_size, false), ConstantInt::get(ctx.types().T_size, 1)); // getfield_unknown is 1 based
3873
+ if (emit_getfield_unknownidx(ctx, ret, obj, idx2, utt, jl_false, order))
3874
+ return true;
3875
+ }
3855
3876
}
3856
3877
}
3857
- // TODO: generic getfield func with more efficient calling convention
3858
3878
return false;
3859
3879
}
3860
3880
@@ -9179,6 +9199,7 @@ static void init_jit_functions(void)
9179
9199
add_named_global("jl_adopt_thread", &jl_adopt_thread);
9180
9200
add_named_global(jlgetcfunctiontrampoline_func, &jl_get_cfunction_trampoline);
9181
9201
add_named_global(jlgetnthfieldchecked_func, &jl_get_nth_field_checked);
9202
+ add_named_global(jlfieldindex_func, &jl_field_index);
9182
9203
add_named_global(diff_gc_total_bytes_func, &jl_gc_diff_total_bytes);
9183
9204
add_named_global(sync_gc_total_bytes_func, &jl_gc_sync_total_bytes);
9184
9205
add_named_global(jlarray_data_owner_func, &jl_array_data_owner);
0 commit comments