@@ -1055,6 +1055,18 @@ static const auto jlgetnthfieldchecked_func = new JuliaFunction{
1055
1055
Attributes (C, {Attribute::NonNull}),
1056
1056
None); },
1057
1057
};
1058
+ static const auto jlfieldindex_func = new JuliaFunction{
1059
+ XSTR (jl_field_index),
1060
+ [](LLVMContext &C) {
1061
+ auto T_prjlvalue = JuliaType::get_prjlvalue_ty (C);
1062
+ return FunctionType::get (getInt32Ty (C),
1063
+ {T_prjlvalue, T_prjlvalue, getInt32Ty (C)}, false );
1064
+ },
1065
+ [](LLVMContext &C) { return AttributeList::get (C,
1066
+ Attributes (C, {Attribute::NoUnwind, Attribute::ReadOnly, Attribute::WillReturn}),
1067
+ AttributeSet (),
1068
+ None); }, // This function can error if the third argument is 1 so don't do that.
1069
+ };
1058
1070
static const auto jlfieldisdefinedchecked_func = new JuliaFunction{
1059
1071
XSTR (jl_field_isdefined_checked),
1060
1072
[](LLVMContext &C) {
@@ -3715,9 +3727,9 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3715
3727
*ret = mark_julia_type (ctx, fld_val, true , jl_any_type);
3716
3728
return true ;
3717
3729
}
3718
- } else if (fld.typ == (jl_value_t *)jl_symbol_type) {
3719
- if (jl_is_datatype (utt) && ! jl_is_namedtuple_type (utt)) { // TODO: Look into this for NamedTuple
3720
- if (jl_struct_try_layout (utt) && ( jl_datatype_nfields (utt) == 1 )) {
3730
+ } else if (fld.typ == (jl_value_t *)jl_symbol_type) { // Known type but unknown symbol
3731
+ if (jl_is_datatype (utt) && (utt != jl_module_type) && jl_struct_try_layout (utt)) {
3732
+ if (( jl_datatype_nfields (utt) == 1 && ! jl_is_namedtuple_type (utt) )) {
3721
3733
jl_svec_t *fn = jl_field_names (utt);
3722
3734
assert (jl_svec_len (fn) == 1 );
3723
3735
Value *typ_sym = literal_pointer_val (ctx, jl_svecref (fn, 0 ));
@@ -3726,6 +3738,15 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3726
3738
*ret = emit_getfield_knownidx (ctx, obj, 0 , utt, order);
3727
3739
return true ;
3728
3740
}
3741
+ else {
3742
+ Value *index = ctx.builder .CreateCall (prepare_call (jlfieldindex_func),
3743
+ {emit_typeof_boxed (ctx, obj, false ), boxed (ctx, fld), ConstantInt::get (getInt32Ty (ctx.builder .getContext ()), 0 )});
3744
+ Value *cond = ctx.builder .CreateICmpNE (index, ConstantInt::get (getInt32Ty (ctx.builder .getContext ()), -1 ));
3745
+ emit_hasnofield_error_ifnot (ctx, cond, utt->name ->name , fld);
3746
+ Value *idx2 = ctx.builder .CreateAdd (ctx.builder .CreateIntCast (index, getSizeTy (ctx.builder .getContext ()), false ), ConstantInt::get (getSizeTy (ctx.builder .getContext ()), 1 )); // getfield_unknown is 1 based
3747
+ if (emit_getfield_unknownidx (ctx, ret, obj, idx2, utt, jl_false, order))
3748
+ return true ;
3749
+ }
3729
3750
}
3730
3751
}
3731
3752
// TODO: generic getfield func with more efficient calling convention
@@ -8774,6 +8795,7 @@ static void init_jit_functions(void)
8774
8795
add_named_global (" jl_adopt_thread" , &jl_adopt_thread);
8775
8796
add_named_global (jlgetcfunctiontrampoline_func, &jl_get_cfunction_trampoline);
8776
8797
add_named_global (jlgetnthfieldchecked_func, &jl_get_nth_field_checked);
8798
+ add_named_global (jlfieldindex_func, &jl_field_index);
8777
8799
add_named_global (diff_gc_total_bytes_func, &jl_gc_diff_total_bytes);
8778
8800
add_named_global (sync_gc_total_bytes_func, &jl_gc_sync_total_bytes);
8779
8801
add_named_global (jlarray_data_owner_func, &jl_array_data_owner);
0 commit comments