@@ -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),
@@ -3236,6 +3243,8 @@ static jl_llvm_functions_t
3236
3243
jl_value_t *jlrettype,
3237
3244
jl_codegen_params_t ¶ms);
3238
3245
3246
+ static void emit_hasnofield_error_ifnot (jl_codectx_t &ctx, Value *ok, jl_sym_t *type, jl_cgval_t name);
3247
+
3239
3248
static bool emit_builtin_call (jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3240
3249
const jl_cgval_t *argv, size_t nargs, jl_value_t *rt,
3241
3250
jl_expr_t *ex, bool is_promotable)
@@ -3706,6 +3715,18 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3706
3715
*ret = mark_julia_type (ctx, fld_val, true , jl_any_type);
3707
3716
return true ;
3708
3717
}
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 )) {
3721
+ jl_svec_t *fn = jl_field_names (utt);
3722
+ assert (jl_svec_len (fn) == 1 );
3723
+ Value *typ_sym = literal_pointer_val (ctx, jl_svecref (fn, 0 ));
3724
+ Value *cond = ctx.builder .CreateICmpEQ (mark_callee_rooted (ctx, typ_sym), mark_callee_rooted (ctx, boxed (ctx, fld)));
3725
+ emit_hasnofield_error_ifnot (ctx, cond, utt->name ->name , fld);
3726
+ *ret = emit_getfield_knownidx (ctx, obj, 0 , utt, order);
3727
+ return true ;
3728
+ }
3729
+ }
3709
3730
}
3710
3731
// TODO: generic getfield func with more efficient calling convention
3711
3732
return false ;
@@ -4426,6 +4447,22 @@ static void undef_var_error_ifnot(jl_codectx_t &ctx, Value *ok, jl_sym_t *name)
4426
4447
ctx.builder .SetInsertPoint (ifok);
4427
4448
}
4428
4449
4450
+ static void emit_hasnofield_error_ifnot (jl_codectx_t &ctx, Value *ok, jl_sym_t *type, jl_cgval_t name)
4451
+ {
4452
+ ++EmittedUndefVarErrors;
4453
+ assert (name.typ == (jl_value_t *)jl_symbol_type);
4454
+ BasicBlock *err = BasicBlock::Create (ctx.builder .getContext (), " err" , ctx.f );
4455
+ BasicBlock *ifok = BasicBlock::Create (ctx.builder .getContext (), " ok" );
4456
+ ctx.builder .CreateCondBr (ok, ifok, err);
4457
+ ctx.builder .SetInsertPoint (err);
4458
+ ctx.builder .CreateCall (prepare_call (jlhasnofield_func),
4459
+ {mark_callee_rooted (ctx, literal_pointer_val (ctx, (jl_value_t *)type)),
4460
+ mark_callee_rooted (ctx, boxed (ctx, name))});
4461
+ ctx.builder .CreateUnreachable ();
4462
+ ctx.f ->getBasicBlockList ().push_back (ifok);
4463
+ ctx.builder .SetInsertPoint (ifok);
4464
+ }
4465
+
4429
4466
// returns a jl_ppvalue_t location for the global variable m.s
4430
4467
// if the reference currently bound or assign == true,
4431
4468
// pbnd will also be assigned with the binding address
@@ -8692,6 +8729,7 @@ static void init_jit_functions(void)
8692
8729
add_named_global (jlatomicerror_func, &jl_atomic_error);
8693
8730
add_named_global (jlthrow_func, &jl_throw);
8694
8731
add_named_global (jlundefvarerror_func, &jl_undefined_var_error);
8732
+ add_named_global (jlhasnofield_func, &jl_has_no_field_error);
8695
8733
add_named_global (jlboundserrorv_func, &jl_bounds_error_ints);
8696
8734
add_named_global (jlboundserror_func, &jl_bounds_error_int);
8697
8735
add_named_global (jlvboundserror_func, &jl_bounds_error_tuple_int);
0 commit comments