@@ -693,6 +693,13 @@ static const auto jlundefvarerror_func = new JuliaFunction{
693
693
{PointerType::get (JuliaType::get_jlvalue_ty (C), AddressSpace::CalleeRooted)}, false ); },
694
694
get_attrs_noreturn,
695
695
};
696
+ static const auto jlhasnofield_func = new JuliaFunction{
697
+ XSTR (jl_has_no_field_error),
698
+ [](LLVMContext &C) { return FunctionType::get (getVoidTy (C),
699
+ {PointerType::get (JuliaType::get_jlvalue_ty (C), AddressSpace::CalleeRooted),
700
+ PointerType::get (JuliaType::get_jlvalue_ty (C), AddressSpace::CalleeRooted)}, false ); },
701
+ get_attrs_noreturn,
702
+ };
696
703
static const auto jlboundserrorv_func = new JuliaFunction{
697
704
XSTR (jl_bounds_error_ints),
698
705
[](LLVMContext &C) { return FunctionType::get (getVoidTy (C),
@@ -1048,6 +1055,18 @@ static const auto jlgetnthfieldchecked_func = new JuliaFunction{
1048
1055
Attributes (C, {Attribute::NonNull}),
1049
1056
None); },
1050
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
+ };
1051
1070
static const auto jlfieldisdefinedchecked_func = new JuliaFunction{
1052
1071
XSTR (jl_field_isdefined_checked),
1053
1072
[](LLVMContext &C) {
@@ -3236,6 +3255,8 @@ static jl_llvm_functions_t
3236
3255
jl_value_t *jlrettype,
3237
3256
jl_codegen_params_t ¶ms);
3238
3257
3258
+ static void emit_hasnofield_error_ifnot (jl_codectx_t &ctx, Value *ok, jl_sym_t *type, jl_cgval_t name);
3259
+
3239
3260
static bool emit_builtin_call (jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3240
3261
const jl_cgval_t *argv, size_t nargs, jl_value_t *rt,
3241
3262
jl_expr_t *ex, bool is_promotable)
@@ -3706,6 +3727,27 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3706
3727
*ret = mark_julia_type (ctx, fld_val, true , jl_any_type);
3707
3728
return true ;
3708
3729
}
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))) {
3733
+ jl_svec_t *fn = jl_field_names (utt);
3734
+ assert (jl_svec_len (fn) == 1 );
3735
+ Value *typ_sym = literal_pointer_val (ctx, jl_svecref (fn, 0 ));
3736
+ Value *cond = ctx.builder .CreateICmpEQ (mark_callee_rooted (ctx, typ_sym), mark_callee_rooted (ctx, boxed (ctx, fld)));
3737
+ emit_hasnofield_error_ifnot (ctx, cond, utt->name ->name , fld);
3738
+ *ret = emit_getfield_knownidx (ctx, obj, 0 , utt, order);
3739
+ return true ;
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
+ }
3750
+ }
3709
3751
}
3710
3752
// TODO: generic getfield func with more efficient calling convention
3711
3753
return false ;
@@ -4426,6 +4468,22 @@ static void undef_var_error_ifnot(jl_codectx_t &ctx, Value *ok, jl_sym_t *name)
4426
4468
ctx.builder .SetInsertPoint (ifok);
4427
4469
}
4428
4470
4471
+ static void emit_hasnofield_error_ifnot (jl_codectx_t &ctx, Value *ok, jl_sym_t *type, jl_cgval_t name)
4472
+ {
4473
+ ++EmittedUndefVarErrors;
4474
+ assert (name.typ == (jl_value_t *)jl_symbol_type);
4475
+ BasicBlock *err = BasicBlock::Create (ctx.builder .getContext (), " err" , ctx.f );
4476
+ BasicBlock *ifok = BasicBlock::Create (ctx.builder .getContext (), " ok" );
4477
+ ctx.builder .CreateCondBr (ok, ifok, err);
4478
+ ctx.builder .SetInsertPoint (err);
4479
+ ctx.builder .CreateCall (prepare_call (jlhasnofield_func),
4480
+ {mark_callee_rooted (ctx, literal_pointer_val (ctx, (jl_value_t *)type)),
4481
+ mark_callee_rooted (ctx, boxed (ctx, name))});
4482
+ ctx.builder .CreateUnreachable ();
4483
+ ctx.f ->getBasicBlockList ().push_back (ifok);
4484
+ ctx.builder .SetInsertPoint (ifok);
4485
+ }
4486
+
4429
4487
// returns a jl_ppvalue_t location for the global variable m.s
4430
4488
// if the reference currently bound or assign == true,
4431
4489
// pbnd will also be assigned with the binding address
@@ -8692,6 +8750,7 @@ static void init_jit_functions(void)
8692
8750
add_named_global (jlatomicerror_func, &jl_atomic_error);
8693
8751
add_named_global (jlthrow_func, &jl_throw);
8694
8752
add_named_global (jlundefvarerror_func, &jl_undefined_var_error);
8753
+ add_named_global (jlhasnofield_func, &jl_has_no_field_error);
8695
8754
add_named_global (jlboundserrorv_func, &jl_bounds_error_ints);
8696
8755
add_named_global (jlboundserror_func, &jl_bounds_error_int);
8697
8756
add_named_global (jlvboundserror_func, &jl_bounds_error_tuple_int);
@@ -8736,6 +8795,7 @@ static void init_jit_functions(void)
8736
8795
add_named_global (" jl_adopt_thread" , &jl_adopt_thread);
8737
8796
add_named_global (jlgetcfunctiontrampoline_func, &jl_get_cfunction_trampoline);
8738
8797
add_named_global (jlgetnthfieldchecked_func, &jl_get_nth_field_checked);
8798
+ add_named_global (jlfieldindex_func, &jl_field_index);
8739
8799
add_named_global (diff_gc_total_bytes_func, &jl_gc_diff_total_bytes);
8740
8800
add_named_global (sync_gc_total_bytes_func, &jl_gc_sync_total_bytes);
8741
8801
add_named_global (jlarray_data_owner_func, &jl_array_data_owner);
0 commit comments